From 5f1ebae3dafe4e5e61824f15c159c603146aa3c0 Mon Sep 17 00:00:00 2001 From: sakumisu <1203593632@qq.com> Date: Sun, 20 Feb 2022 20:51:38 +0800 Subject: [PATCH] use cdc acm template.c for test in all demo --- .../User/main.c => cdc_acm_template.c} | 140 +- demo/ch32/ch32v307/SRC/Core/core_riscv.c | 539 ---- .../SRC/Peripheral/src/ch32v30x_gpio.c | 568 ---- .../SRC/Peripheral/src/ch32v30x_rcc.c | 1391 ---------- .../USB/USBFS/DEVICE/cdc_acm/.project | 79 - .../org.eclipse.core.resources.prefs | 2 - .../USB/USBFS/DEVICE/cdc_acm/.template | 13 - .../DEVICE/cdc_acm/USB_Stack_CDC_ACM.wvproj | 2 - .../cdc_acm/手动添加usb_stack外部路径.png | Bin 91466 -> 0 bytes .../CH32V307VCT6}/.cproject | 69 +- demo/ch32/usb_device/CH32V307VCT6/.launch | 61 + demo/ch32/usb_device/CH32V307VCT6/.project | 37 + .../.settings/language.settings.xml | 2 +- demo/ch32/usb_device/CH32V307VCT6/.template | 15 + .../CH32V307VCT6/CH32V307VCT6.wvproj | Bin 0 -> 202 bytes .../CherryUSB/class/audio/usb_audio.h | 708 +++++ .../CherryUSB/class/audio/usbd_audio.c | 153 ++ .../CherryUSB/class/audio/usbd_audio.h | 43 + .../CherryUSB/class/cdc/usb_cdc.h | 444 ++++ .../CherryUSB/class/cdc/usbd_cdc.c | 171 ++ .../CherryUSB/class/cdc/usbd_cdc.h | 42 + .../CherryUSB/class/cdc/usbh_cdc_acm.c | 343 +++ .../CherryUSB/class/cdc/usbh_cdc_acm.h | 52 + .../CherryUSB/class/dfu/usb_dfu.h | 103 + .../CherryUSB/class/dfu/usbd_dfu.c | 87 + .../CherryUSB/class/dfu/usbd_dfu.h | 38 + .../CherryUSB/class/hid/usb_hid.h | 708 +++++ .../CherryUSB/class/hid/usbd_hid.c | 285 +++ .../CherryUSB/class/hid/usbd_hid.h | 50 + .../CherryUSB/class/hid/usbh_hid.c | 284 ++ .../CherryUSB/class/hid/usbh_hid.h | 45 + .../CherryUSB/class/hub/usb_hub.h | 120 + .../CherryUSB/class/hub/usbd_hub.c | 106 + .../CherryUSB/class/hub/usbd_hub.h | 38 + .../CherryUSB/class/hub/usbh_hub.c | 532 ++++ .../CherryUSB/class/hub/usbh_hub.h | 42 + .../CherryUSB/class/midi/usb_midi.h | 174 ++ .../CherryUSB/class/msc/usb_msc.h | 121 + .../CherryUSB/class/msc/usb_scsi.h | 986 +++++++ .../CherryUSB/class/msc/usbd_msc.c | 993 +++++++ .../CherryUSB/class/msc/usbd_msc.h | 30 + .../CherryUSB/class/msc/usbh_msc.c | 439 ++++ .../CherryUSB/class/msc/usbh_msc.h | 49 + .../CherryUSB/class/tmc/usb_tmc.h | 130 + .../CherryUSB/class/video/usb_video.h | 1162 +++++++++ .../CherryUSB/class/video/usbd_video.c | 752 ++++++ .../CherryUSB/class/video/usbd_video.h | 44 + .../CH32V307VCT6/CherryUSB/common/usb_dc.h | 200 ++ .../CH32V307VCT6/CherryUSB/common/usb_def.h | 671 +++++ .../CH32V307VCT6/CherryUSB/common/usb_errno.h | 340 +++ .../CH32V307VCT6/CherryUSB/common/usb_hc.h | 213 ++ .../CH32V307VCT6/CherryUSB/common/usb_list.h | 473 ++++ .../CH32V307VCT6/CherryUSB/common/usb_mem.h | 75 + .../CH32V307VCT6/CherryUSB/common/usb_util.h | 300 +++ .../CH32V307VCT6/CherryUSB/core/usbd_core.c | 1299 ++++++++++ .../CH32V307VCT6/CherryUSB/core/usbd_core.h | 138 + .../CH32V307VCT6/CherryUSB/core/usbh_core.c | 990 +++++++ .../CH32V307VCT6/CherryUSB/core/usbh_core.h | 128 + .../CherryUSB/usb_ch32_usbfs_reg.h | 339 +++ .../CH32V307VCT6/CherryUSB/usb_dc_usbfs.c | 630 +++++ .../usb_device/CH32V307VCT6/Core/core_riscv.c | 380 +++ .../CH32V307VCT6}/Core/core_riscv.h | 244 +- .../CH32V307VCT6}/Debug/debug.c | 75 +- .../CH32V307VCT6}/Debug/debug.h | 0 .../CH32V307VCT6}/Ld/Link.ld | 0 .../CH32V307VCT6}/Peripheral/inc/ch32v30x.h | 346 +-- .../Peripheral/inc/ch32v30x_adc.h | 226 ++ .../Peripheral/inc/ch32v30x_bkp.h | 95 + .../Peripheral/inc/ch32v30x_can.h | 364 +++ .../Peripheral/inc/ch32v30x_crc.h | 35 + .../Peripheral/inc/ch32v30x_dac.h | 122 + .../Peripheral/inc/ch32v30x_dbgmcu.h | 48 + .../Peripheral/inc/ch32v30x_dma.h | 266 ++ .../Peripheral/inc/ch32v30x_dvp.h | 65 + .../Peripheral/inc/ch32v30x_eth.h | 1323 ++++++++++ .../Peripheral/inc/ch32v30x_exti.h | 88 + .../Peripheral/inc/ch32v30x_flash.h | 157 ++ .../Peripheral/inc/ch32v30x_fsmc.h | 318 +++ .../Peripheral/inc/ch32v30x_gpio.h | 33 +- .../Peripheral/inc/ch32v30x_i2c.h | 208 ++ .../Peripheral/inc/ch32v30x_iwdg.h | 54 + .../Peripheral/inc/ch32v30x_misc.h | 0 .../Peripheral/inc/ch32v30x_opa.h | 72 + .../Peripheral/inc/ch32v30x_pwr.h | 62 + .../Peripheral/inc/ch32v30x_rcc.h | 13 +- .../Peripheral/inc/ch32v30x_rng.h | 39 + .../Peripheral/inc/ch32v30x_rtc.h | 52 + .../Peripheral/inc/ch32v30x_sdio.h | 252 ++ .../Peripheral/inc/ch32v30x_spi.h | 227 ++ .../Peripheral/inc/ch32v30x_tim.h | 513 ++++ .../Peripheral/inc/ch32v30x_usart.h | 0 .../Peripheral/inc/ch32v30x_wwdg.h | 40 + .../Peripheral/src/ch32v30x_adc.c | 1094 ++++++++ .../Peripheral/src/ch32v30x_bkp.c | 221 ++ .../Peripheral/src/ch32v30x_can.c | 1138 ++++++++ .../Peripheral/src/ch32v30x_crc.c | 92 + .../Peripheral/src/ch32v30x_dac.c | 269 ++ .../Peripheral/src/ch32v30x_dbgmcu.c | 60 + .../Peripheral/src/ch32v30x_dma.c | 669 +++++ .../Peripheral/src/ch32v30x_dvp.c | 118 + .../Peripheral/src/ch32v30x_eth.c | 2280 +++++++++++++++++ .../Peripheral/src/ch32v30x_exti.c | 157 ++ .../Peripheral/src/ch32v30x_flash.c | 895 +++++++ .../Peripheral/src/ch32v30x_fsmc.c | 653 +++++ .../Peripheral/src/ch32v30x_gpio.c | 490 ++++ .../Peripheral/src/ch32v30x_i2c.c | 883 +++++++ .../Peripheral/src/ch32v30x_iwdg.c | 109 + .../Peripheral/src/ch32v30x_misc.c | 55 +- .../Peripheral/src/ch32v30x_opa.c | 75 + .../Peripheral/src/ch32v30x_pwr.c | 328 +++ .../Peripheral/src/ch32v30x_rcc.c | 1235 +++++++++ .../Peripheral/src/ch32v30x_rng.c | 132 + .../Peripheral/src/ch32v30x_rtc.c | 244 ++ .../Peripheral/src/ch32v30x_sdio.c | 574 +++++ .../Peripheral/src/ch32v30x_spi.c | 587 +++++ .../Peripheral/src/ch32v30x_tim.c | 2117 +++++++++++++++ .../Peripheral/src/ch32v30x_usart.c | 596 ++--- .../Peripheral/src/ch32v30x_wwdg.c | 123 + .../CH32V307VCT6}/Startup/startup_ch32v30x.S | 0 .../CH32V307VCT6/User/cdc_acm_template.c} | 101 +- .../CH32V307VCT6}/User/ch32v30x_conf.h | 18 + .../CH32V307VCT6}/User/ch32v30x_it.c | 26 +- .../CH32V307VCT6}/User/ch32v30x_it.h | 0 demo/ch32/usb_device/CH32V307VCT6/User/main.c | 63 + .../CH32V307VCT6}/User/system_ch32v30x.c | 246 +- .../CH32V307VCT6}/User/system_ch32v30x.h | 0 ..._init.c => hid_custom_keyboard_template.c} | 117 +- ...eyboard_init.c => hid_keyboard_template.c} | 189 +- .../hid_mouse_init.c => hid_mouse_template.c} | 97 +- demo/mm32/KEIL_PRJ/USB_VCOM.uvoptx | 28 +- demo/mm32/KEIL_PRJ/USB_VCOM.uvprojx | 9 +- demo/mm32/bsp/main.c | 158 +- .../msc_ram_init.c => msc_ram_template.c} | 94 +- .../usb_device/stm32f103c8t6/Core/Src/main.c | 234 +- .../stm32f103c8t6/Core/Src/stm32f1xx_it.c | 10 +- .../MDK-ARM/stm32f103c8t6.uvoptx | 148 +- .../MDK-ARM/stm32f103c8t6.uvprojx | 149 +- .../stm32f103c8t6/example/example_select.h | 18 - .../usb_device/stm32f429igt6/Core/Src/main.c | 2 +- .../usb_device/stm32h743vbt6/Core/Src/main.c | 2 +- 140 files changed, 35953 insertions(+), 4655 deletions(-) rename demo/{ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/main.c => cdc_acm_template.c} (53%) delete mode 100644 demo/ch32/ch32v307/SRC/Core/core_riscv.c delete mode 100644 demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_gpio.c delete mode 100644 demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_rcc.c delete mode 100644 demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.project delete mode 100644 demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.settings/org.eclipse.core.resources.prefs delete mode 100644 demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.template delete mode 100644 demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/USB_Stack_CDC_ACM.wvproj delete mode 100644 demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/手动添加usb_stack外部路径.png rename demo/ch32/{ch32v307/USB/USBFS/DEVICE/cdc_acm => usb_device/CH32V307VCT6}/.cproject (67%) create mode 100644 demo/ch32/usb_device/CH32V307VCT6/.launch create mode 100644 demo/ch32/usb_device/CH32V307VCT6/.project rename demo/ch32/{ch32v307/USB/USBFS/DEVICE/cdc_acm => usb_device/CH32V307VCT6}/.settings/language.settings.xml (94%) create mode 100644 demo/ch32/usb_device/CH32V307VCT6/.template create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CH32V307VCT6.wvproj create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/audio/usb_audio.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/audio/usbd_audio.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/audio/usbd_audio.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usb_cdc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbd_cdc.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbd_cdc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbh_cdc_acm.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbh_cdc_acm.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usb_dfu.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usbd_dfu.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usbd_dfu.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usb_hid.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbd_hid.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbd_hid.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbh_hid.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbh_hid.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usb_hub.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbd_hub.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbd_hub.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbh_hub.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbh_hub.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/midi/usb_midi.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usb_msc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usb_scsi.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbd_msc.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbd_msc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbh_msc.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbh_msc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/tmc/usb_tmc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usb_video.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usbd_video.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usbd_video.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_dc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_def.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_errno.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_hc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_list.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_mem.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_util.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbd_core.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbd_core.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbh_core.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbh_core.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/usb_ch32_usbfs_reg.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/CherryUSB/usb_dc_usbfs.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Core/core_riscv.c rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Core/core_riscv.h (62%) rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Debug/debug.c (74%) rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Debug/debug.h (100%) rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Ld/Link.ld (100%) rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Peripheral/inc/ch32v30x.h (97%) create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_adc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_bkp.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_can.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_crc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dac.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dbgmcu.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dma.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dvp.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_eth.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_exti.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_flash.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_fsmc.h rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Peripheral/inc/ch32v30x_gpio.h (82%) create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_i2c.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_iwdg.h rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Peripheral/inc/ch32v30x_misc.h (100%) create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_opa.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_pwr.h rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Peripheral/inc/ch32v30x_rcc.h (96%) create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rng.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rtc.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_sdio.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_spi.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_tim.h rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Peripheral/inc/ch32v30x_usart.h (100%) create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_wwdg.h create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_adc.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_bkp.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_can.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_crc.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dac.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dbgmcu.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dma.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dvp.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_eth.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_exti.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_flash.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_fsmc.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_gpio.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_i2c.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_iwdg.c rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Peripheral/src/ch32v30x_misc.c (63%) create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_opa.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_pwr.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rcc.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rng.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rtc.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_sdio.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_spi.c create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_tim.c rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Peripheral/src/ch32v30x_usart.c (50%) create mode 100644 demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_wwdg.c rename demo/ch32/{ch32v307/SRC => usb_device/CH32V307VCT6}/Startup/startup_ch32v30x.S (100%) rename demo/{stm32/usb_device/stm32f103c8t6/example/cdc/cdc_init.c => ch32/usb_device/CH32V307VCT6/User/cdc_acm_template.c} (62%) rename demo/ch32/{ch32v307/USB/USBFS/DEVICE/cdc_acm => usb_device/CH32V307VCT6}/User/ch32v30x_conf.h (54%) rename demo/ch32/{ch32v307/USB/USBFS/DEVICE/cdc_acm => usb_device/CH32V307VCT6}/User/ch32v30x_it.c (60%) rename demo/ch32/{ch32v307/USB/USBFS/DEVICE/cdc_acm => usb_device/CH32V307VCT6}/User/ch32v30x_it.h (100%) create mode 100644 demo/ch32/usb_device/CH32V307VCT6/User/main.c rename demo/ch32/{ch32v307/USB/USBFS/DEVICE/cdc_acm => usb_device/CH32V307VCT6}/User/system_ch32v30x.c (76%) rename demo/ch32/{ch32v307/USB/USBFS/DEVICE/cdc_acm => usb_device/CH32V307VCT6}/User/system_ch32v30x.h (100%) rename demo/{stm32/usb_device/stm32f103c8t6/example/hid_custom/hid_custom_init.c => hid_custom_keyboard_template.c} (84%) rename demo/{stm32/usb_device/stm32f103c8t6/example/hid_keyboard/hid_keyboard_init.c => hid_keyboard_template.c} (57%) rename demo/{stm32/usb_device/stm32f103c8t6/example/hid_mouse/hid_mouse_init.c => hid_mouse_template.c} (77%) rename demo/{stm32/usb_device/stm32f103c8t6/example/msc_ram/msc_ram_init.c => msc_ram_template.c} (56%) delete mode 100644 demo/stm32/usb_device/stm32f103c8t6/example/example_select.h diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/main.c b/demo/cdc_acm_template.c similarity index 53% rename from demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/main.c rename to demo/cdc_acm_template.c index 12fc0c13..d12b0a47 100644 --- a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/main.c +++ b/demo/cdc_acm_template.c @@ -1,15 +1,3 @@ -/********************************** (C) COPYRIGHT ******************************* -* File Name : main.c -* Author : sakumisu -* Version : V1.0.0 -* Date : 2022/01/02 -* Description : cdc acm test. -*******************************************************************************/ - -/* - *@Note -*/ -#include "debug.h" #include "usbd_core.h" #include "usbd_cdc.h" @@ -28,7 +16,7 @@ /*!< global descriptor */ static const uint8_t cdc_descriptor[] = { - USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x02, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02), /////////////////////////////////////// @@ -38,33 +26,35 @@ static const uint8_t cdc_descriptor[] = { /////////////////////////////////////// /// string1 descriptor /////////////////////////////////////// - 0x12, /* bLength */ + 0x14, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ /////////////////////////////////////// /// string2 descriptor /////////////////////////////////////// - 0x24, /* bLength */ + 0x26, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ - ' ', 0x00, /* wcChar8 */ - 'C', 0x00, /* wcChar9 */ - 'D', 0x00, /* wcChar10 */ - 'C', 0x00, /* wcChar11 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ + ' ', 0x00, /* wcChar9 */ + 'C', 0x00, /* wcChar10 */ + 'D', 0x00, /* wcChar11 */ + 'C', 0x00, /* wcChar12 */ ' ', 0x00, /* wcChar13 */ 'D', 0x00, /* wcChar14 */ 'E', 0x00, /* wcChar15 */ @@ -78,13 +68,13 @@ static const uint8_t cdc_descriptor[] = { '2', 0x00, /* wcChar0 */ '0', 0x00, /* wcChar1 */ '2', 0x00, /* wcChar2 */ - '1', 0x00, /* wcChar3 */ - '0', 0x00, /* wcChar4 */ - '3', 0x00, /* wcChar5 */ - '1', 0x00, /* wcChar6 */ - '0', 0x00, /* wcChar7 */ - '0', 0x00, /* wcChar8 */ - '0', 0x00, /* wcChar9 */ + '2', 0x00, /* wcChar3 */ + '1', 0x00, /* wcChar4 */ + '2', 0x00, /* wcChar5 */ + '3', 0x00, /* wcChar6 */ + '4', 0x00, /* wcChar7 */ + '5', 0x00, /* wcChar8 */ + '6', 0x00, /* wcChar9 */ #ifdef CONFIG_USB_HS /////////////////////////////////////// /// device qualifier descriptor @@ -102,6 +92,7 @@ static const uint8_t cdc_descriptor[] = { #endif 0x00 }; + /*!< class */ usbd_class_t cdc_class; /*!< interface one */ @@ -114,8 +105,12 @@ void usbd_cdc_acm_out(uint8_t ep) { uint8_t data[64]; uint32_t read_byte; - + usbd_ep_read(ep, data, 64, &read_byte); + for (uint8_t i = 0; i < read_byte; i++) { + printf("%02x ", data[i]); + } + printf("\r\n"); printf("read len:%d\r\n", read_byte); usbd_ep_read(ep, NULL, 0, NULL); } @@ -137,7 +132,7 @@ usbd_endpoint_t cdc_in_ep = { }; /* function ------------------------------------------------------------------*/ -void cdc_init(void) +void cdc_acm_init(void) { usbd_desc_register(cdc_descriptor); /*!< add interface */ @@ -146,28 +141,9 @@ void cdc_init(void) /*!< interface add endpoint */ usbd_interface_add_endpoint(&cdc_data_intf, &cdc_out_ep); usbd_interface_add_endpoint(&cdc_data_intf, &cdc_in_ep); -} -void usb_dc_low_level_init(void) -{ - RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY); - RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE); - RCC_USBHSConfig(RCC_USBPLL_Div2); - RCC_USBHSPLLCKREFCLKConfig(RCC_USBHSPLLCKREFCLK_4M); - RCC_USBHSPHYPLLALIVEcmd(ENABLE); -#ifdef CONFIG_USB_HS - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE); -#else - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); -#endif - - Delay_Us(100); -#ifndef CONFIG_USB_HS - //EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN; - NVIC_EnableIRQ(OTG_FS_IRQn); -#else - NVIC_EnableIRQ( USBHS_IRQn ); -#endif + extern int usb_dc_init(void); + usb_dc_init(); } volatile uint8_t dtr_enable = 0; @@ -181,34 +157,10 @@ void usbd_cdc_acm_set_dtr(bool dtr) } } -/********************************************************************* - * @fn main - * - * @brief Main program. - * - * @return none - */ -int main(void) +void cdc_acm_data_send_with_dtr_test(void) { - Delay_Init(); - USART_Printf_Init(115200); - printf("SystemClk:%d\r\n", SystemCoreClock); - - Delay_Ms(10); - - cdc_init(); - extern int usb_dc_init(void); - usb_dc_init(); - - while (!usb_device_is_configured()) { + if (dtr_enable) { + uint8_t data_buffer[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x31, 0x32, 0x33, 0x34, 0x35 }; + usbd_ep_write(CDC_IN_EP, data_buffer, 10, NULL); } - while (1) { - if(dtr_enable) - { - uint8_t data_buffer[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x31, 0x32, 0x33, 0x34, 0x35 }; - usbd_ep_write(0x81, data_buffer, 10, NULL); - Delay_Ms(500); - } - - } -} +} \ No newline at end of file diff --git a/demo/ch32/ch32v307/SRC/Core/core_riscv.c b/demo/ch32/ch32v307/SRC/Core/core_riscv.c deleted file mode 100644 index 601a677b..00000000 --- a/demo/ch32/ch32v307/SRC/Core/core_riscv.c +++ /dev/null @@ -1,539 +0,0 @@ -/********************************** (C) COPYRIGHT ******************************* -* File Name : core_riscv.c -* Author : WCH -* Version : V1.0.0 -* Date : 2021/06/06 -* Description : RISC-V Core Peripheral Access Layer Source File -*******************************************************************************/ -#include - -/* define compiler specific symbols */ -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */ - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - -#endif - - -/********************************************************************* - * @fn __get_FFLAGS - * - * @brief Return the Floating-Point Accrued Exceptions - * - * @return fflags value - */ -uint32_t __get_FFLAGS(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "fflags" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_FFLAGS - * - * @brief Set the Floating-Point Accrued Exceptions - * - * @param value - set FFLAGS value - * - * @return none - */ -void __set_FFLAGS(uint32_t value) -{ - __ASM volatile ("csrw fflags, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_FRM - * - * @brief Return the Floating-Point Dynamic Rounding Mode - * - * @return frm value - */ -uint32_t __get_FRM(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "frm" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_FRM - * - * @brief Set the Floating-Point Dynamic Rounding Mode - * - * @param value - set frm value - * - * @return none - */ -void __set_FRM(uint32_t value) -{ - __ASM volatile ("csrw frm, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_FCSR - * - * @brief Return the Floating-Point Control and Status Register - * - * @return fcsr value - */ -uint32_t __get_FCSR(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "fcsr" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_FCSR - * - * @brief Set the Floating-Point Dynamic Rounding Mode - * - * @param value - set fcsr value - * - * @return none - */ -void __set_FCSR(uint32_t value) -{ - __ASM volatile ("csrw fcsr, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MSTATUS - * - * @brief Return the Machine Status Register - * - * @return mstatus value - */ -uint32_t __get_MSTATUS(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mstatus" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MSTATUS - * - * @brief Set the Machine Status Register - * - * @param value - set mstatus value - * - * @return none - */ -void __set_MSTATUS(uint32_t value) -{ - __ASM volatile ("csrw mstatus, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MISA - * - * @brief Return the Machine ISA Register - * - * @return misa value - */ -uint32_t __get_MISA(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "misa" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MISA - * - * @brief Set the Machine ISA Register - * - * @param value - set misa value - * - * @return none - */ -void __set_MISA(uint32_t value) -{ - __ASM volatile ("csrw misa, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MIE - * - * @brief Return the Machine Interrupt Enable Register - * - * @return mie value - */ -uint32_t __get_MIE(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mie" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MISA - * - * @brief Set the Machine ISA Register - * - * @param value - set mie value - * - * @return none - */ -void __set_MIE(uint32_t value) -{ - __ASM volatile ("csrw mie, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MTVEC - * - * @brief Return the Machine Trap-Vector Base-Address Register - * - * @return mtvec value - */ -uint32_t __get_MTVEC(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mtvec" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MTVEC - * - * @brief Set the Machine Trap-Vector Base-Address Register - * - * @param value - set mtvec value - * - * @return none - */ -void __set_MTVEC(uint32_t value) -{ - __ASM volatile ("csrw mtvec, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MTVEC - * - * @brief Return the Machine Seratch Register - * - * @return mscratch value - */ -uint32_t __get_MSCRATCH(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mscratch" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MTVEC - * - * @brief Set the Machine Seratch Register - * - * @param value - set mscratch value - * - * @return none - */ -void __set_MSCRATCH(uint32_t value) -{ - __ASM volatile ("csrw mscratch, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MEPC - * - * @brief Return the Machine Exception Program Register - * - * @return mepc value - */ -uint32_t __get_MEPC(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mepc" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MEPC - * - * @brief Set the Machine Exception Program Register - * - * @return mepc value - */ -void __set_MEPC(uint32_t value) -{ - __ASM volatile ("csrw mepc, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MCAUSE - * - * @brief Return the Machine Cause Register - * - * @return mcause value - */ -uint32_t __get_MCAUSE(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mcause" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MEPC - * - * @brief Set the Machine Cause Register - * - * @return mcause value - */ -void __set_MCAUSE(uint32_t value) -{ - __ASM volatile ("csrw mcause, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MTVAL - * - * @brief Return the Machine Trap Value Register - * - * @return mtval value - */ -uint32_t __get_MTVAL(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mtval" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MTVAL - * - * @brief Set the Machine Trap Value Register - * - * @return mtval value - */ -void __set_MTVAL(uint32_t value) -{ - __ASM volatile ("csrw mtval, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MIP - * - * @brief Return the Machine Interrupt Pending Register - * - * @return mip value - */ -uint32_t __get_MIP(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mip" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MIP - * - * @brief Set the Machine Interrupt Pending Register - * - * @return mip value - */ -void __set_MIP(uint32_t value) -{ - __ASM volatile ("csrw mip, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MCYCLE - * - * @brief Return Lower 32 bits of Cycle counter - * - * @return mcycle value - */ -uint32_t __get_MCYCLE(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mcycle" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MCYCLE - * - * @brief Set Lower 32 bits of Cycle counter - * - * @return mcycle value - */ -void __set_MCYCLE(uint32_t value) -{ - __ASM volatile ("csrw mcycle, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MCYCLEH - * - * @brief Return Upper 32 bits of Cycle counter - * - * @return mcycleh value - */ -uint32_t __get_MCYCLEH(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mcycleh" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MCYCLEH - * - * @brief Set Upper 32 bits of Cycle counter - * - * @return mcycleh value - */ -void __set_MCYCLEH(uint32_t value) -{ - __ASM volatile ("csrw mcycleh, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MINSTRET - * - * @brief Return Lower 32 bits of Instructions-retired counter - * - * @return mcause value - */ -uint32_t __get_MINSTRET(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "minstret" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MINSTRET - * - * @brief Set Lower 32 bits of Instructions-retired counter - * - * @return minstret value - */ -void __set_MINSTRET(uint32_t value) -{ - __ASM volatile ("csrw minstret, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MINSTRETH - * - * @brief Return Upper 32 bits of Instructions-retired counter - * - * @return minstreth value - */ -uint32_t __get_MINSTRETH(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "minstreth" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __set_MINSTRETH - * - * @brief Set Upper 32 bits of Instructions-retired counter - * - * @return minstreth value - */ -void __set_MINSTRETH(uint32_t value) -{ - __ASM volatile ("csrw minstreth, %0" : : "r" (value) ); -} - -/********************************************************************* - * @fn __get_MVENDORID - * - * @brief Return Vendor ID Register - * - * @return mvendorid value - */ -uint32_t __get_MVENDORID(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mvendorid" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __get_MARCHID - * - * @brief Return Machine Architecture ID Register - * - * @return marchid value - */ -uint32_t __get_MARCHID(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "marchid" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __get_MIMPID - * - * @brief Return Machine Implementation ID Register - * - * @return mimpid value - */ -uint32_t __get_MIMPID(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mimpid" : "=r" (result) ); - return (result); -} - -/********************************************************************* - * @fn __get_MHARTID - * - * @brief Return Hart ID Register - * - * @return mhartid value - */ -uint32_t __get_MHARTID(void) -{ - uint32_t result; - - __ASM volatile ( "csrr %0," "mhartid" : "=r" (result) ); - return (result); -} - - - diff --git a/demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_gpio.c b/demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_gpio.c deleted file mode 100644 index 5109bd8a..00000000 --- a/demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_gpio.c +++ /dev/null @@ -1,568 +0,0 @@ -/********************************** (C) COPYRIGHT ******************************* -* File Name : ch32v30x_gpio.c -* Author : WCH -* Version : V1.0.0 -* Date : 2021/06/06 -* Description : This file provides all the GPIO firmware functions. -*******************************************************************************/ -#include "ch32v30x_gpio.h" -#include "ch32v30x_rcc.h" - -/* MASK */ -#define ECR_PORTPINCONFIG_MASK ((uint16_t)0xFF80) -#define LSB_MASK ((uint16_t)0xFFFF) -#define DBGAFR_POSITION_MASK ((uint32_t)0x000F0000) -#define DBGAFR_SWJCFG_MASK ((uint32_t)0xF0FFFFFF) -#define DBGAFR_LOCATION_MASK ((uint32_t)0x00200000) -#define DBGAFR_NUMBITS_MASK ((uint32_t)0x00100000) - - -/********************************************************************* - * @fn GPIO_DeInit - * - * @brief Deinitializes the GPIOx peripheral registers to their default - * reset values. - * - * @param GPIOx - where x can be (A..G) to select the GPIO peripheral. - * - * @return none - */ -void GPIO_DeInit(GPIO_TypeDef* GPIOx) -{ - if (GPIOx == GPIOA) - { - RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE); - RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE); - } - else if (GPIOx == GPIOB) - { - RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE); - RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE); - } - else if (GPIOx == GPIOC) - { - RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, ENABLE); - RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, DISABLE); - } - else if (GPIOx == GPIOD) - { - RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, ENABLE); - RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, DISABLE); - } - else if (GPIOx == GPIOE) - { - RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOE, ENABLE); - RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOE, DISABLE); - } -} - -/********************************************************************* - * @fn GPIO_AFIODeInit - * - * @brief Deinitializes the Alternate Functions (remap, event control - * and EXTI configuration) registers to their default reset values. - * - * @return none - */ -void GPIO_AFIODeInit(void) -{ - RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, ENABLE); - RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, DISABLE); -} - -/********************************************************************* - * @fn GPIO_Init - * - * @brief GPIOx - where x can be (A..G) to select the GPIO peripheral. - * - * @param GPIO_InitStruct - pointer to a GPIO_InitTypeDef structure that - * contains the configuration information for the specified GPIO peripheral. - * - * @return none - */ -void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) -{ - uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; - uint32_t tmpreg = 0x00, pinmask = 0x00; - - currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F); - - if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) - { - currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; - } - - if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00) - { - tmpreg = GPIOx->CFGLR; - - for (pinpos = 0x00; pinpos < 0x08; pinpos++) - { - pos = ((uint32_t)0x01) << pinpos; - currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; - - if (currentpin == pos) - { - pos = pinpos << 2; - pinmask = ((uint32_t)0x0F) << pos; - tmpreg &= ~pinmask; - tmpreg |= (currentmode << pos); - - if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) - { - GPIOx->BCR = (((uint32_t)0x01) << pinpos); - } - else - { - if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) - { - GPIOx->BSHR = (((uint32_t)0x01) << pinpos); - } - } - } - } - GPIOx->CFGLR = tmpreg; - } - - if (GPIO_InitStruct->GPIO_Pin > 0x00FF) - { - tmpreg = GPIOx->CFGHR; - - for (pinpos = 0x00; pinpos < 0x08; pinpos++) - { - pos = (((uint32_t)0x01) << (pinpos + 0x08)); - currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos); - - if (currentpin == pos) - { - pos = pinpos << 2; - pinmask = ((uint32_t)0x0F) << pos; - tmpreg &= ~pinmask; - tmpreg |= (currentmode << pos); - - if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) - { - GPIOx->BCR = (((uint32_t)0x01) << (pinpos + 0x08)); - } - - if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) - { - GPIOx->BSHR = (((uint32_t)0x01) << (pinpos + 0x08)); - } - } - } - GPIOx->CFGHR = tmpreg; - } -} - -/********************************************************************* - * @fn GPIO_StructInit - * - * @brief Fills each GPIO_InitStruct member with its default - * - * @param GPIO_InitStruct - pointer to a GPIO_InitTypeDef structure - * which will be initialized. - * - * @return none - */ -void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct) -{ - GPIO_InitStruct->GPIO_Pin = GPIO_Pin_All; - GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN_FLOATING; -} - -/********************************************************************* - * @fn GPIO_ReadInputDataBit - * - * @brief GPIOx - where x can be (A..G) to select the GPIO peripheral. - * - * @param GPIO_Pin - specifies the port bit to read. - * This parameter can be GPIO_Pin_x where x can be (0..15). - * - * @return The input port pin value. - */ -uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) -{ - uint8_t bitstatus = 0x00; - - if ((GPIOx->INDR & GPIO_Pin) != (uint32_t)Bit_RESET) - { - bitstatus = (uint8_t)Bit_SET; - } - else - { - bitstatus = (uint8_t)Bit_RESET; - } - - return bitstatus; -} - -/********************************************************************* - * @fn GPIO_ReadInputData - * - * @brief Reads the specified GPIO input data port. - * - * @param GPIOx - where x can be (A..G) to select the GPIO peripheral. - * - * @return The output port pin value. - */ -uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx) -{ - return ((uint16_t)GPIOx->INDR); -} - -/********************************************************************* - * @fn GPIO_ReadOutputDataBit - * - * @brief Reads the specified output data port bit. - * - * @param GPIOx - where x can be (A..G) to select the GPIO peripheral. - * GPIO_Pin - specifies the port bit to read. - * This parameter can be GPIO_Pin_x where x can be (0..15). - * - * @return none - */ -uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) -{ - uint8_t bitstatus = 0x00; - - if ((GPIOx->OUTDR & GPIO_Pin) != (uint32_t)Bit_RESET) - { - bitstatus = (uint8_t)Bit_SET; - } - else - { - bitstatus = (uint8_t)Bit_RESET; - } - - return bitstatus; -} - -/********************************************************************* - * @fn GPIO_ReadOutputData - * - * @brief Reads the specified GPIO output data port. - * - * @param GPIOx - where x can be (A..G) to select the GPIO peripheral. - * - * @return GPIO output port pin value. - */ -uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx) -{ - return ((uint16_t)GPIOx->OUTDR); -} - -/********************************************************************* - * @fn GPIO_SetBits - * - * @brief Sets the selected data port bits. - * - * @param GPIOx - where x can be (A..G) to select the GPIO peripheral. - * GPIO_Pin - specifies the port bits to be written. - * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). - * - * @return none - */ -void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) -{ - GPIOx->BSHR = GPIO_Pin; -} - -/********************************************************************* - * @fn GPIO_ResetBits - * - * @brief Clears the selected data port bits. - * - * @param GPIOx - where x can be (A..G) to select the GPIO peripheral. - * GPIO_Pin - specifies the port bits to be written. - * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). - * - * @return none - */ -void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) -{ - GPIOx->BCR = GPIO_Pin; -} - -/********************************************************************* - * @fn GPIO_WriteBit - * - * @brief Sets or clears the selected data port bit. - * - * @param GPIO_Pin - specifies the port bit to be written. - * This parameter can be one of GPIO_Pin_x where x can be (0..15). - * BitVal - specifies the value to be written to the selected bit. - * Bit_SetL - to clear the port pin. - * Bit_SetH - to set the port pin. - * - * @return none - */ -void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal) -{ - if (BitVal != Bit_RESET) - { - GPIOx->BSHR = GPIO_Pin; - } - else - { - GPIOx->BCR = GPIO_Pin; - } -} - -/********************************************************************* - * @fn GPIO_Write - * - * @brief Writes data to the specified GPIO data port. - * - * @param GPIOx - where x can be (A..G) to select the GPIO peripheral. - * PortVal - specifies the value to be written to the port output data register. - * - * @return none - */ -void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal) -{ - GPIOx->OUTDR = PortVal; -} - -/********************************************************************* - * @fn GPIO_PinLockConfig - * - * @brief Locks GPIO Pins configuration registers. - * - * @param GPIOx - where x can be (A..G) to select the GPIO peripheral. - * GPIO_Pin - specifies the port bit to be written. - * This parameter can be any combination of GPIO_Pin_x where x can be (0..15). - * - * @return none - */ -void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) -{ - uint32_t tmp = 0x00010000; - - tmp |= GPIO_Pin; - GPIOx->LCKR = tmp; - GPIOx->LCKR = GPIO_Pin; - GPIOx->LCKR = tmp; - tmp = GPIOx->LCKR; - tmp = GPIOx->LCKR; -} - -/********************************************************************* - * @fn GPIO_EventOutputConfig - * - * @brief Selects the GPIO pin used as Event output. - * - * @param GPIO_PortSource - selects the GPIO port to be used as source - * for Event output. - * This parameter can be GPIO_PortSourceGPIOx where x can be (A..E). - * GPIO_PinSource - specifies the pin for the Event output. - * This parameter can be GPIO_PinSourcex where x can be (0..15). - * - * @return none - */ -void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) -{ - uint32_t tmpreg = 0x00; - - tmpreg = AFIO->ECR; - tmpreg &= ECR_PORTPINCONFIG_MASK; - tmpreg |= (uint32_t)GPIO_PortSource << 0x04; - tmpreg |= GPIO_PinSource; - AFIO->ECR = tmpreg; -} - -/********************************************************************* - * @fn GPIO_EventOutputCmd - * - * @brief Enables or disables the Event Output. - * - * @param NewState - ENABLE or DISABLE. - * - * @return none - */ -void GPIO_EventOutputCmd(FunctionalState NewState) -{ - if(NewState) - { - AFIO->ECR |= (1<<7); - } - else - { - AFIO->ECR &= ~(1<<7); - } -} - -/********************************************************************* - * @fn GPIO_PinRemapConfig - * - * @brief Changes the mapping of the specified pin. - * - * @param GPIO_Remap - selects the pin to remap. - * GPIO_Remap_SPI1 - SPI1 Alternate Function mapping - * GPIO_Remap_I2C1 - I2C1 Alternate Function mapping - * GPIO_Remap_USART1 - USART1 Alternate Function mapping - * GPIO_Remap_USART2 - USART2 Alternate Function mapping - * GPIO_PartialRemap_USART3 - USART3 Partial Alternate Function mapping - * GPIO_FullRemap_USART3 - USART3 Full Alternate Function mapping - * GPIO_PartialRemap_TIM1 - TIM1 Partial Alternate Function mapping - * GPIO_FullRemap_TIM1 - TIM1 Full Alternate Function mapping - * GPIO_PartialRemap1_TIM2 - TIM2 Partial1 Alternate Function mapping - * GPIO_PartialRemap2_TIM2 - TIM2 Partial2 Alternate Function mapping - * GPIO_FullRemap_TIM2 - TIM2 Full Alternate Function mapping - * GPIO_PartialRemap_TIM3 - TIM3 Partial Alternate Function mapping - * GPIO_FullRemap_TIM3 - TIM3 Full Alternate Function mapping - * GPIO_Remap_TIM4 - TIM4 Alternate Function mapping - * GPIO_Remap1_CAN1 - CAN1 Alternate Function mapping - * GPIO_Remap2_CAN1 - CAN1 Alternate Function mapping - * GPIO_Remap_PD01 - PD01 Alternate Function mapping - * GPIO_Remap_ADC1_ETRGINJ - ADC1 External Trigger Injected Conversion remapping - * GPIO_Remap_ADC1_ETRGREG - ADC1 External Trigger Regular Conversion remapping - * GPIO_Remap_ADC2_ETRGINJ - ADC2 External Trigger Injected Conversion remapping - * GPIO_Remap_ADC2_ETRGREG - ADC2 External Trigger Regular Conversion remapping - * GPIO_Remap_ETH - Ethernet remapping - * GPIO_Remap_CAN2 - CAN2 remapping - * GPIO_Remap_MII_RMII_SEL - MII or RMII selection - * GPIO_Remap_SWJ_NoJTRST - Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST - * GPIO_Remap_SWJ_JTAGDisable - JTAG-DP Disabled and SW-DP Enabled - * GPIO_Remap_SWJ_Disable - Full SWJ Disabled (JTAG-DP + SW-DP) - * GPIO_Remap_TIM2ITR1_PTP_SOF - Ethernet PTP output or USB OTG SOF (Start of Frame) connected - * to TIM2 Internal Trigger 1 for calibration - * GPIO_Remap_TIM2ITR1_PTP_SOF - Ethernet PTP output or USB OTG SOF (Start of Frame) - * GPIO_Remap_TIM8 - TIM8 Alternate Function mapping - * GPIO_PartialRemap_TIM9 - TIM9 Partial Alternate Function mapping - * GPIO_FullRemap_TIM9 - TIM9 Full Alternate Function mapping - * GPIO_PartialRemap_TIM10 - TIM10 Partial Alternate Function mapping - * GPIO_FullRemap_TIM10 - TIM10 Full Alternate Function mapping - * GPIO_Remap_FSMC_NADV - FSMC_NADV Alternate Function mapping - * GPIO_PartialRemap_USART4 - USART4 Partial Alternate Function mapping - * GPIO_FullRemap_USART4 - USART4 Full Alternate Function mapping - * GPIO_PartialRemap_USART5 - USART5 Partial Alternate Function mapping - * GPIO_FullRemap_USART5 - USART5 Full Alternate Function mapping - * GPIO_PartialRemap_USART6 - USART6 Partial Alternate Function mapping - * GPIO_FullRemap_USART6 - USART6 Full Alternate Function mapping - * GPIO_PartialRemap_USART7 - USART7 Partial Alternate Function mapping - * GPIO_FullRemap_USART7 - USART7 Full Alternate Function mapping - * GPIO_PartialRemap_USART8 - USART8 Partial Alternate Function mapping - * GPIO_FullRemap_USART8 - USART8 Full Alternate Function mapping - * GPIO_Remap_USART1_HighBit - USART1 Alternate Function mapping high bit - * NewState - ENABLE or DISABLE. - * - * @return none - */ -void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState) -{ - uint32_t tmp = 0x00, tmp1 = 0x00, tmpreg = 0x00, tmpmask = 0x00; - - if((GPIO_Remap & 0x80000000) == 0x80000000) - { - tmpreg = AFIO->PCFR2; - } - else - { - tmpreg = AFIO->PCFR1; - } - - tmpmask = (GPIO_Remap & DBGAFR_POSITION_MASK) >> 0x10; - tmp = GPIO_Remap & LSB_MASK; - - /* Clear bit */ - if((GPIO_Remap & 0x80000000) == 0x80000000){ /* PCFR2 */ - if ((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) /* [31:16] 2bit */ - { - tmp1 = ((uint32_t)0x03) << (tmpmask+0x10); - tmpreg &= ~tmp1; - } - else if ((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK) /* [15:0] 2bit */ - { - tmp1 = ((uint32_t)0x03) << tmpmask; - tmpreg &= ~tmp1; - } - else /* [31:0] 1bit */ - { - tmpreg &= ~(tmp << ((GPIO_Remap >> 0x15)*0x10)); - } - - } - else{ /* PCFR1 */ - if ((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) /* [26:24] 3bit SWD_JTAG */ - { - tmpreg &= DBGAFR_SWJCFG_MASK; - AFIO->PCFR1 &= DBGAFR_SWJCFG_MASK; - } - else if ((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK) /* [15:0] 2bit */ - { - tmp1 = ((uint32_t)0x03) << tmpmask; - tmpreg &= ~tmp1; - tmpreg |= ~DBGAFR_SWJCFG_MASK; - } - else /* [31:0] 1bit */ - { - tmpreg &= ~(tmp << ((GPIO_Remap >> 0x15)*0x10)); - tmpreg |= ~DBGAFR_SWJCFG_MASK; - } - } - - /* Set bit */ - if (NewState != DISABLE) - { - tmpreg |= (tmp << ((GPIO_Remap >> 0x15)*0x10)); - } - - if((GPIO_Remap & 0x80000000) == 0x80000000) - { - AFIO->PCFR2 = tmpreg; - } - else - { - AFIO->PCFR1 = tmpreg; - } -} - -/********************************************************************* - * @fn GPIO_EXTILineConfig - * - * @brief Selects the GPIO pin used as EXTI Line. - * - * @param GPIO_PortSource - selects the GPIO port to be used as source for EXTI lines. - * This parameter can be GPIO_PortSourceGPIOx where x can be (A..G). - * GPIO_PinSource - specifies the EXTI line to be configured. - * This parameter can be GPIO_PinSourcex where x can be (0..15). - * - * @return none - */ -void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) -{ - uint32_t tmp = 0x00; - - tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)); - AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp; - AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03))); -} - -/********************************************************************* - * @fn GPIO_ETH_MediaInterfaceConfig - * - * @brief Selects the Ethernet media interface. - * - * @param GPIO_ETH_MediaInterface - specifies the Media Interface mode. - * GPIO_ETH_MediaInterface_MII - MII mode - * GPIO_ETH_MediaInterface_RMII - RMII mode - * - * @return none - */ -void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface) -{ - if(GPIO_ETH_MediaInterface) - { - AFIO->PCFR1 |= (1<<23); - } - else - { - AFIO->PCFR1 &= ~(1<<23); - } -} - - - - diff --git a/demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_rcc.c b/demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_rcc.c deleted file mode 100644 index 4778acee..00000000 --- a/demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_rcc.c +++ /dev/null @@ -1,1391 +0,0 @@ -/********************************** (C) COPYRIGHT ******************************* -* File Name : ch32v30x_rcc.c -* Author : WCH -* Version : V1.0.0 -* Date : 2021/06/06 -* Description : This file provides all the RCC firmware functions. -*******************************************************************************/ -#include "ch32v30x_rcc.h" - -/* RCC registers bit address in the alias region */ -#define RCC_OFFSET (RCC_BASE - PERIPH_BASE) - -/* BDCTLR Register */ -#define BDCTLR_OFFSET (RCC_OFFSET + 0x20) - -/* RCC registers bit mask */ - -/* CTLR register bit mask */ -#define CTLR_HSEBYP_Reset ((uint32_t)0xFFFBFFFF) -#define CTLR_HSEBYP_Set ((uint32_t)0x00040000) -#define CTLR_HSEON_Reset ((uint32_t)0xFFFEFFFF) -#define CTLR_HSEON_Set ((uint32_t)0x00010000) -#define CTLR_HSITRIM_Mask ((uint32_t)0xFFFFFF07) - -#define CFGR0_PLL_Mask ((uint32_t)0xFFC0FFFF) /* 103 */ -#define CFGR0_PLL_Mask_1 ((uint32_t)0xFFC2FFFF) /* 107 */ - -#define CFGR0_PLLMull_Mask ((uint32_t)0x003C0000) -#define CFGR0_PLLSRC_Mask ((uint32_t)0x00010000) -#define CFGR0_PLLXTPRE_Mask ((uint32_t)0x00020000) -#define CFGR0_SWS_Mask ((uint32_t)0x0000000C) -#define CFGR0_SW_Mask ((uint32_t)0xFFFFFFFC) -#define CFGR0_HPRE_Reset_Mask ((uint32_t)0xFFFFFF0F) -#define CFGR0_HPRE_Set_Mask ((uint32_t)0x000000F0) -#define CFGR0_PPRE1_Reset_Mask ((uint32_t)0xFFFFF8FF) -#define CFGR0_PPRE1_Set_Mask ((uint32_t)0x00000700) -#define CFGR0_PPRE2_Reset_Mask ((uint32_t)0xFFFFC7FF) -#define CFGR0_PPRE2_Set_Mask ((uint32_t)0x00003800) -#define CFGR0_ADCPRE_Reset_Mask ((uint32_t)0xFFFF3FFF) -#define CFGR0_ADCPRE_Set_Mask ((uint32_t)0x0000C000) - -/* RSTSCKR register bit mask */ -#define RSTSCKR_RMVF_Set ((uint32_t)0x01000000) - -/* CFGR2 register bit mask */ -#define CFGR2_PREDIV1SRC ((uint32_t)0x00010000) -#define CFGR2_PREDIV1 ((uint32_t)0x0000000F) -#define CFGR2_PREDIV2 ((uint32_t)0x000000F0) -#define CFGR2_PLL2MUL ((uint32_t)0x00000F00) -#define CFGR2_PLL3MUL ((uint32_t)0x0000F000) - -/* RCC Flag Mask */ -#define FLAG_Mask ((uint8_t)0x1F) - -/* INTR register byte 2 (Bits[15:8]) base address */ -#define INTR_BYTE2_ADDRESS ((uint32_t)0x40021009) - -/* INTR register byte 3 (Bits[23:16]) base address */ -#define INTR_BYTE3_ADDRESS ((uint32_t)0x4002100A) - -/* CFGR0 register byte 4 (Bits[31:24]) base address */ -#define CFGR0_BYTE4_ADDRESS ((uint32_t)0x40021007) - -/* BDCTLR register base address */ -#define BDCTLR_ADDRESS (PERIPH_BASE + BDCTLR_OFFSET) - - -static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9}; -static __I uint8_t ADCPrescTable[4] = {2, 4, 6, 8}; - -/********************************************************************* - * @fn RCC_DeInit - * - * @brief Resets the RCC clock configuration to the default reset state. - * - * @return none - */ -void RCC_DeInit(void) -{ - RCC->CTLR |= (uint32_t)0x00000001; - RCC->CFGR0 &= (uint32_t)0xF8FF0000; - RCC->CTLR &= (uint32_t)0xFEF6FFFF; - RCC->CTLR &= (uint32_t)0xFFFBFFFF; - RCC->CFGR0 &= (uint32_t)0xFF80FFFF; - RCC->INTR = 0x009F0000; -} - -/********************************************************************* - * @fn RCC_HSEConfig - * - * @brief Configures the External High Speed oscillator (HSE). - * - * @param RCC_HSE - - * RCC_HSE_OFF - HSE oscillator OFF. - * RCC_HSE_ON - HSE oscillator ON. - * RCC_HSE_Bypass - HSE oscillator bypassed with external clock. - * - * @return none - */ -void RCC_HSEConfig(uint32_t RCC_HSE) -{ - RCC->CTLR &= CTLR_HSEON_Reset; - RCC->CTLR &= CTLR_HSEBYP_Reset; - - switch(RCC_HSE) - { - case RCC_HSE_ON: - RCC->CTLR |= CTLR_HSEON_Set; - break; - - case RCC_HSE_Bypass: - RCC->CTLR |= CTLR_HSEBYP_Set | CTLR_HSEON_Set; - break; - - default: - break; - } -} - -/********************************************************************* - * @fn RCC_WaitForHSEStartUp - * - * @brief Waits for HSE start-up. - * - * @return SUCCESS - HSE oscillator is stable and ready to use. - * ERROR - HSE oscillator not yet ready. - */ -ErrorStatus RCC_WaitForHSEStartUp(void) -{ - __IO uint32_t StartUpCounter = 0; - - ErrorStatus status = ERROR; - FlagStatus HSEStatus = RESET; - - do - { - HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY); - StartUpCounter++; - } while((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET)); - - if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET) - { - status = SUCCESS; - } - else - { - status = ERROR; - } - - return (status); -} - -/********************************************************************* - * @fn RCC_AdjustHSICalibrationValue - * - * @brief Adjusts the Internal High Speed oscillator (HSI) calibration value. - * - * @param HSICalibrationValue - specifies the calibration trimming value. - * This parameter must be a number between 0 and 0x1F. - * - * @return none - */ -void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CTLR; - tmpreg &= CTLR_HSITRIM_Mask; - tmpreg |= (uint32_t)HSICalibrationValue << 3; - RCC->CTLR = tmpreg; -} - -/********************************************************************* - * @fn RCC_HSICmd - * - * @brief Enables or disables the Internal High Speed oscillator (HSI). - * - * @param NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_HSICmd(FunctionalState NewState) -{ - if(NewState) - { - RCC->CTLR |= (1<<0); - } - else{ - RCC->CTLR &= ~(1<<0); - } -} - -/********************************************************************* - * @fn RCC_PLLConfig - * - * @brief Configures the PLL clock source and multiplication factor. - * - * @param RCC_PLLSource - specifies the PLL entry clock source. - * RCC_PLLSource_HSI_Div2 - HSI oscillator clock divided by 2 - * selected as PLL clock entry. - * RCC_PLLSource_PREDIV1 - PREDIV1 clock selected as PLL clock - * entry. - * RCC_PLLMul - specifies the PLL multiplication factor. - * This parameter can be RCC_PLLMul_x where x:[2,16]. - * For CH32V307 - - * RCC_PLLMul_18_EXTEN - * RCC_PLLMul_3_EXTEN - * RCC_PLLMul_4_EXTEN - * RCC_PLLMul_5_EXTEN - * RCC_PLLMul_6_EXTEN - * RCC_PLLMul_7_EXTEN - * RCC_PLLMul_8_EXTEN - * RCC_PLLMul_9_EXTEN - * RCC_PLLMul_10_EXTEN - * RCC_PLLMul_11_EXTEN - * RCC_PLLMul_12_EXTEN - * RCC_PLLMul_13_EXTEN - * RCC_PLLMul_14_EXTEN - * RCC_PLLMul_6_5_EXTEN - * RCC_PLLMul_15_EXTEN - * RCC_PLLMul_16_EXTEN - * For other CH32V30x - - * RCC_PLLMul_2 - * RCC_PLLMul_3 - * RCC_PLLMul_4 - * RCC_PLLMul_5 - * RCC_PLLMul_6 - * RCC_PLLMul_7 - * RCC_PLLMul_8 - * RCC_PLLMul_9 - * RCC_PLLMul_10 - * RCC_PLLMul_11 - * RCC_PLLMul_12 - * RCC_PLLMul_13 - * RCC_PLLMul_14 - * RCC_PLLMul_15 - * RCC_PLLMul_16 - * RCC_PLLMul_18 - * - * @return none - */ -void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CFGR0; - - if(((*(uint32_t*)0x1FFFF70C) & (1<<14)) != (1<<14)){ /* for other CH32V30x */ - tmpreg &= CFGR0_PLL_Mask; - } - else{ /* for CH32V307 */ - tmpreg &= CFGR0_PLL_Mask_1; - } - - tmpreg |= RCC_PLLSource | RCC_PLLMul; - RCC->CFGR0 = tmpreg; -} - -/********************************************************************* - * @fn RCC_PLLCmd - * - * @brief Enables or disables the PLL. - * - * @param NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_PLLCmd(FunctionalState NewState) -{ - if(NewState) - { - RCC->CTLR |= (1<<24); - } - else{ - RCC->CTLR &= ~(1<<24); - } -} - -/********************************************************************* - * @fn RCC_SYSCLKConfig - * - * @brief Configures the system clock (SYSCLK). - * - * @param RCC_SYSCLKSource - specifies the clock source used as system clock. - * RCC_SYSCLKSource_HSI - HSI selected as system clock. - * RCC_SYSCLKSource_HSE - HSE selected as system clock. - * RCC_SYSCLKSource_PLLCLK - PLL selected as system clock. - * - * @return none - */ -void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CFGR0; - tmpreg &= CFGR0_SW_Mask; - tmpreg |= RCC_SYSCLKSource; - RCC->CFGR0 = tmpreg; -} - -/********************************************************************* - * @fn RCC_GetSYSCLKSource - * - * @brief Returns the clock source used as system clock. - * - * @return 0x00 - HSI used as system clock. - * 0x04 - HSE used as system clock. - * 0x08 - PLL used as system clock. - */ -uint8_t RCC_GetSYSCLKSource(void) -{ - return ((uint8_t)(RCC->CFGR0 & CFGR0_SWS_Mask)); -} - -/********************************************************************* - * @fn RCC_HCLKConfig - * - * @brief Configures the AHB clock (HCLK). - * - * @param RCC_SYSCLK - defines the AHB clock divider. This clock is derived from - * the system clock (SYSCLK). - * RCC_SYSCLK_Div1 - AHB clock = SYSCLK. - * RCC_SYSCLK_Div2 - AHB clock = SYSCLK/2. - * RCC_SYSCLK_Div4 - AHB clock = SYSCLK/4. - * RCC_SYSCLK_Div8 - AHB clock = SYSCLK/8. - * RCC_SYSCLK_Div16 - AHB clock = SYSCLK/16. - * RCC_SYSCLK_Div64 - AHB clock = SYSCLK/64. - * RCC_SYSCLK_Div128 - AHB clock = SYSCLK/128. - * RCC_SYSCLK_Div256 - AHB clock = SYSCLK/256. - * RCC_SYSCLK_Div512 - AHB clock = SYSCLK/512. - * - * @return none - */ -void RCC_HCLKConfig(uint32_t RCC_SYSCLK) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CFGR0; - tmpreg &= CFGR0_HPRE_Reset_Mask; - tmpreg |= RCC_SYSCLK; - RCC->CFGR0 = tmpreg; -} - -/********************************************************************* - * @fn RCC_PCLK1Config - * - * @brief Configures the Low Speed APB clock (PCLK1). - * - * @param RCC_HCLK - defines the APB1 clock divider. This clock is derived from - * the AHB clock (HCLK). - * RCC_HCLK_Div1 - APB1 clock = HCLK. - * RCC_HCLK_Div2 - APB1 clock = HCLK/2. - * RCC_HCLK_Div4 - APB1 clock = HCLK/4. - * RCC_HCLK_Div8 - APB1 clock = HCLK/8. - * RCC_HCLK_Div16 - APB1 clock = HCLK/16. - * - * @return none - */ -void RCC_PCLK1Config(uint32_t RCC_HCLK) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CFGR0; - tmpreg &= CFGR0_PPRE1_Reset_Mask; - tmpreg |= RCC_HCLK; - RCC->CFGR0 = tmpreg; -} - -/********************************************************************* - * @fn RCC_PCLK2Config - * - * @brief Configures the High Speed APB clock (PCLK2). - * - * @param RCC_HCLK - defines the APB2 clock divider. This clock is derived from - * the AHB clock (HCLK). - * RCC_HCLK_Div1 - APB1 clock = HCLK. - * RCC_HCLK_Div2 - APB1 clock = HCLK/2. - * RCC_HCLK_Div4 - APB1 clock = HCLK/4. - * RCC_HCLK_Div8 - APB1 clock = HCLK/8. - * RCC_HCLK_Div16 - APB1 clock = HCLK/16. - * - * @return none - */ -void RCC_PCLK2Config(uint32_t RCC_HCLK) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CFGR0; - tmpreg &= CFGR0_PPRE2_Reset_Mask; - tmpreg |= RCC_HCLK << 3; - RCC->CFGR0 = tmpreg; -} - -/********************************************************************* - * @fn RCC_ITConfig - * - * @brief Enables or disables the specified RCC interrupts. - * - * @param RCC_IT - specifies the RCC interrupt sources to be enabled or disabled. - * RCC_IT_LSIRDY - LSI ready interrupt. - * RCC_IT_LSERDY - LSE ready interrupt. - * RCC_IT_HSIRDY - HSI ready interrupt. - * RCC_IT_HSERDY - HSE ready interrupt. - * RCC_IT_PLLRDY - PLL ready interrupt. - * NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState) -{ - if (NewState != DISABLE) - { - *(__IO uint8_t *) INTR_BYTE2_ADDRESS |= RCC_IT; - } - else - { - *(__IO uint8_t *) INTR_BYTE2_ADDRESS &= (uint8_t)~RCC_IT; - } -} - -/********************************************************************* - * @fn RCC_ADCCLKConfig - * - * @brief Configures the ADC clock (ADCCLK). - * - * @param RCC_PCLK2 - defines the ADC clock divider. This clock is derived from - * the APB2 clock (PCLK2). - * RCC_PCLK2_Div2 - ADC clock = PCLK2/2. - * RCC_PCLK2_Div4 - ADC clock = PCLK2/4. - * RCC_PCLK2_Div6 - ADC clock = PCLK2/6. - * RCC_PCLK2_Div8 - ADC clock = PCLK2/8. - * - * @return none - */ -void RCC_ADCCLKConfig(uint32_t RCC_PCLK2) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CFGR0; - tmpreg &= CFGR0_ADCPRE_Reset_Mask; - tmpreg |= RCC_PCLK2; - RCC->CFGR0 = tmpreg; -} - -/********************************************************************* - * @fn RCC_LSEConfig - * - * @brief Configures the External Low Speed oscillator (LSE). - * - * @param RCC_LSE - specifies the new state of the LSE. - * RCC_LSE_OFF - LSE oscillator OFF. - * RCC_LSE_ON - LSE oscillator ON. - * RCC_LSE_Bypass - LSE oscillator bypassed with external clock. - * - * @return none - */ -void RCC_LSEConfig(uint8_t RCC_LSE) -{ - *(__IO uint8_t *) BDCTLR_ADDRESS = RCC_LSE_OFF; - *(__IO uint8_t *) BDCTLR_ADDRESS = RCC_LSE_OFF; - - switch(RCC_LSE) - { - case RCC_LSE_ON: - *(__IO uint8_t *) BDCTLR_ADDRESS = RCC_LSE_ON; - break; - - case RCC_LSE_Bypass: - *(__IO uint8_t *) BDCTLR_ADDRESS = RCC_LSE_Bypass | RCC_LSE_ON; - break; - - default: - break; - } -} - -/********************************************************************* - * @fn RCC_LSICmd - * - * @brief Enables or disables the Internal Low Speed oscillator (LSI). - * - * @param NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_LSICmd(FunctionalState NewState) -{ - if(NewState) - { - RCC->RSTSCKR |= (1<<0); - } - else{ - RCC->RSTSCKR &= ~(1<<0); - } -} - -/********************************************************************* - * @fn RCC_RTCCLKConfig - * - * @brief Once the RTC clock is selected it can't be changed unless the Backup domain is reset. - * - * @param RCC_RTCCLKSource - specifies the RTC clock source. - * RCC_RTCCLKSource_LSE - LSE selected as RTC clock. - * RCC_RTCCLKSource_LSI - LSI selected as RTC clock. - * RCC_RTCCLKSource_HSE_Div128 - HSE clock divided by 128 selected as RTC clock. - * - * @return none - */ -void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource) -{ - RCC->BDCTLR |= RCC_RTCCLKSource; -} - -/********************************************************************* - * @fn RCC_RTCCLKCmd - * - * @brief This function must be used only after the RTC clock was selected - * using the RCC_RTCCLKConfig function. - * - * @param NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_RTCCLKCmd(FunctionalState NewState) -{ - if(NewState) - { - RCC->BDCTLR |= (1<<15); - } - else{ - RCC->BDCTLR &= ~(1<<15); - } -} - -/********************************************************************* - * @fn RCC_GetClocksFreq - * - * @brief The result of this function could be not correct when using - * fractional value for HSE crystal. - * - * @param RCC_Clocks - pointer to a RCC_ClocksTypeDef structure which will hold - * the clocks frequencies. - * - * @return none - */ -void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) -{ - uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0, Pll_6_5 = 0; - - tmp = RCC->CFGR0 & CFGR0_SWS_Mask; - - switch (tmp) - { - case 0x00: - RCC_Clocks->SYSCLK_Frequency = HSI_VALUE; - break; - - case 0x04: - RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; - break; - - case 0x08: - pllmull = RCC->CFGR0 & CFGR0_PLLMull_Mask; - pllsource = RCC->CFGR0 & CFGR0_PLLSRC_Mask; - - pllmull = ( pllmull >> 18) + 2; - - if(((*(uint32_t*)0x1FFFF70C) & (1<<14)) != (1<<14)){ /* for other CH32V30x */ - if(pllmull == 17) pllmull = 18; - } - else{ /* for CH32V307 */ - if(pllmull == 2) pllmull = 18; - if(pllmull == 15){ - pllmull = 13; /* *6.5 */ - Pll_6_5 = 1; - } - if(pllmull == 16) pllmull = 15; - if(pllmull == 17) pllmull = 16; - } - - - if (pllsource == 0x00) - { - if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE){ - RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE) * pllmull; - } - else{ - RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >>1) * pllmull; - } - } - else - { - if ((RCC->CFGR0 & CFGR0_PLLXTPRE_Mask) != (uint32_t)RESET) - { - RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE >> 1) * pllmull; - } - else - { - RCC_Clocks->SYSCLK_Frequency = HSE_VALUE * pllmull; - } - } - - if(Pll_6_5 == 1) RCC_Clocks->SYSCLK_Frequency = (RCC_Clocks->SYSCLK_Frequency / 2); - - break; - - default: - RCC_Clocks->SYSCLK_Frequency = HSI_VALUE; - break; - } - - tmp = RCC->CFGR0 & CFGR0_HPRE_Set_Mask; - tmp = tmp >> 4; - presc = APBAHBPrescTable[tmp]; - RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc; - tmp = RCC->CFGR0 & CFGR0_PPRE1_Set_Mask; - tmp = tmp >> 8; - presc = APBAHBPrescTable[tmp]; - RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc; - tmp = RCC->CFGR0 & CFGR0_PPRE2_Set_Mask; - tmp = tmp >> 11; - presc = APBAHBPrescTable[tmp]; - RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc; - tmp = RCC->CFGR0 & CFGR0_ADCPRE_Set_Mask; - tmp = tmp >> 14; - presc = ADCPrescTable[tmp]; - RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc; -} - -/********************************************************************* - * @fn RCC_AHBPeriphClockCmd - * - * @brief Enables or disables the AHB peripheral clock. - * - * @param RCC_AHBPeriph - specifies the AHB peripheral to gates its clock. - * RCC_AHBPeriph_DMA1. - * RCC_AHBPeriph_DMA2. - * RCC_AHBPeriph_SRAM. - * RCC_AHBPeriph_CRC. - * RCC_AHBPeriph_FSMC - * RCC_AHBPeriph_RNG - * RCC_AHBPeriph_SDIO - * RCC_AHBPeriph_USBHS - * RCC_AHBPeriph_OTG_FS - * RCC_AHBPeriph_DVP - * RCC_AHBPeriph_ETH_MAC - * RCC_AHBPeriph_ETH_MAC_Tx - * RCC_AHBPeriph_ETH_MAC_Rx - * NewState: ENABLE or DISABLE. - * - * @return none - */ -void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) -{ - if (NewState != DISABLE) - { - RCC->AHBPCENR |= RCC_AHBPeriph; - } - else - { - RCC->AHBPCENR &= ~RCC_AHBPeriph; - } -} - -/********************************************************************* - * @fn RCC_APB2PeriphClockCmd - * - * @brief Enables or disables the High Speed APB (APB2) peripheral clock. - * - * @param RCC_APB2Periph - specifies the APB2 peripheral to gates its clock. - * RCC_APB2Periph_AFIO. - * RCC_APB2Periph_GPIOA. - * RCC_APB2Periph_GPIOB. - * RCC_APB2Periph_GPIOC. - * RCC_APB2Periph_GPIOD. - * RCC_APB2Periph_GPIOE - * RCC_APB2Periph_ADC1. - * RCC_APB2Periph_ADC2 - * RCC_APB2Periph_TIM1. - * RCC_APB2Periph_SPI1. - * RCC_APB2Periph_TIM8 - * RCC_APB2Periph_USART1. - * RCC_APB2Periph_TIM9 - * RCC_APB2Periph_TIM10 - * NewState - ENABLE or DISABLE - * - * @return none - */ -void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) -{ - if (NewState != DISABLE) - { - RCC->APB2PCENR |= RCC_APB2Periph; - } - else - { - RCC->APB2PCENR &= ~RCC_APB2Periph; - } -} - -/********************************************************************* - * @fn RCC_APB1PeriphClockCmd - * - * @brief Enables or disables the Low Speed APB (APB1) peripheral clock. - * - * @param RCC_APB1Periph - specifies the APB1 peripheral to gates its clock. - * RCC_APB1Periph_TIM2. - * RCC_APB1Periph_TIM3. - * RCC_APB1Periph_TIM4. - * RCC_APB1Periph_TIM5 - * RCC_APB1Periph_TIM6 - * RCC_APB1Periph_TIM7 - * RCC_APB1Periph_UART6 - * RCC_APB1Periph_UART7 - * RCC_APB1Periph_UART8 - * RCC_APB1Periph_WWDG. - * RCC_APB1Periph_SPI2. - * RCC_APB1Periph_SPI3. - * RCC_APB1Periph_USART2. - * RCC_APB1Periph_USART3. - * RCC_APB1Periph_UART4 - * RCC_APB1Periph_UART5 - * RCC_APB1Periph_I2C1. - * RCC_APB1Periph_I2C2. - * RCC_APB1Periph_USB. - * RCC_APB1Periph_CAN1. - * RCC_APB1Periph_BKP. - * RCC_APB1Periph_PWR. - * RCC_APB1Periph_DAC. - * NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) -{ - if (NewState != DISABLE) - { - RCC->APB1PCENR |= RCC_APB1Periph; - } - else - { - RCC->APB1PCENR &= ~RCC_APB1Periph; - } -} - -/********************************************************************* - * @fn RCC_APB2PeriphResetCmd - * - * @brief Forces or releases High Speed APB (APB2) peripheral reset. - * - * @param RCC_APB2Periph - specifies the APB2 peripheral to reset. - * RCC_APB2Periph_AFIO. - * RCC_APB2Periph_GPIOA. - * RCC_APB2Periph_GPIOB. - * RCC_APB2Periph_GPIOC. - * RCC_APB2Periph_GPIOD. - * RCC_APB2Periph_GPIOE - * RCC_APB2Periph_ADC1. - * RCC_APB2Periph_ADC2 - * RCC_APB2Periph_TIM1. - * RCC_APB2Periph_SPI1. - * RCC_APB2Periph_TIM8 - * RCC_APB2Periph_USART1. - * RCC_APB2Periph_TIM9 - * RCC_APB2Periph_TIM10 - * NewState - ENABLE or DISABLE - * - * @return none - */ -void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) -{ - if (NewState != DISABLE) - { - RCC->APB2PRSTR |= RCC_APB2Periph; - } - else - { - RCC->APB2PRSTR &= ~RCC_APB2Periph; - } -} - -/********************************************************************* - * @fn RCC_APB1PeriphResetCmd - * - * @brief Forces or releases Low Speed APB (APB1) peripheral reset. - * - * @param RCC_APB1Periph - specifies the APB1 peripheral to reset. - * RCC_APB1Periph_TIM2. - * RCC_APB1Periph_TIM3. - * RCC_APB1Periph_TIM4. - * RCC_APB1Periph_TIM5 - * RCC_APB1Periph_TIM6 - * RCC_APB1Periph_TIM7 - * RCC_APB1Periph_UART6 - * RCC_APB1Periph_UART7 - * RCC_APB1Periph_UART8 - * RCC_APB1Periph_WWDG. - * RCC_APB1Periph_SPI2. - * RCC_APB1Periph_SPI3. - * RCC_APB1Periph_USART2. - * RCC_APB1Periph_USART3. - * RCC_APB1Periph_UART4 - * RCC_APB1Periph_UART5 - * RCC_APB1Periph_I2C1. - * RCC_APB1Periph_I2C2. - * RCC_APB1Periph_USB. - * RCC_APB1Periph_CAN1. - * RCC_APB1Periph_BKP. - * RCC_APB1Periph_PWR. - * RCC_APB1Periph_DAC. - * NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) -{ - if (NewState != DISABLE) - { - RCC->APB1PRSTR |= RCC_APB1Periph; - } - else - { - RCC->APB1PRSTR &= ~RCC_APB1Periph; - } -} - -/********************************************************************* - * @fn RCC_BackupResetCmd - * - * @brief Forces or releases the Backup domain reset. - * - * @param NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_BackupResetCmd(FunctionalState NewState) -{ - if(NewState) - { - RCC->BDCTLR |= (1<<16); - } - else{ - RCC->BDCTLR &= ~(1<<16); - } -} - -/********************************************************************* - * @fn RCC_ClockSecuritySystemCmd - * - * @brief Enables or disables the Clock Security System. - * - * @param NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_ClockSecuritySystemCmd(FunctionalState NewState) -{ - if(NewState) - { - RCC->CTLR |= (1<<19); - } - else{ - RCC->CTLR &= ~(1<<19); - } -} - -/********************************************************************* - * @fn RCC_MCOConfig - * - * @brief Selects the clock source to output on MCO pin. - * - * @param RCC_MCO - specifies the clock source to output. - * RCC_MCO_NoClock - No clock selected. - * RCC_MCO_SYSCLK - System clock selected. - * RCC_MCO_HSI - HSI oscillator clock selected. - * RCC_MCO_HSE - HSE oscillator clock selected. - * RCC_MCO_PLLCLK_Div2 - PLL clock divided by 2 selected. - * RCC_MCO_PLL2CLK - PLL2 clock selected - * RCC_MCO_PLL3CLK_Div2 - PLL3 clock divided by 2 selected - * RCC_MCO_XT1 - External 3-25 MHz oscillator clock selected - * RCC_MCO_PLL3CLK - PLL3 clock selected - * - * @return none - */ -void RCC_MCOConfig(uint8_t RCC_MCO) -{ - *(__IO uint8_t *) CFGR0_BYTE4_ADDRESS = RCC_MCO; -} - -/********************************************************************* - * @fn RCC_GetFlagStatus - * - * @brief Checks whether the specified RCC flag is set or not. - * - * @param RCC_FLAG - specifies the flag to check. - * RCC_FLAG_HSIRDY - HSI oscillator clock ready. - * RCC_FLAG_HSERDY - HSE oscillator clock ready. - * RCC_FLAG_PLLRDY - PLL clock ready. - * RCC_FLAG_PLL2RDY - PLL2 clock ready. - * RCC_FLAG_PLL3RDY - PLL3 clock ready. - * RCC_FLAG_LSERDY - LSE oscillator clock ready. - * RCC_FLAG_LSIRDY - LSI oscillator clock ready. - * RCC_FLAG_PINRST - Pin reset. - * RCC_FLAG_PORRST - POR/PDR reset. - * RCC_FLAG_SFTRST - Software reset. - * RCC_FLAG_IWDGRST - Independent Watchdog reset. - * RCC_FLAG_WWDGRST - Window Watchdog reset. - * RCC_FLAG_LPWRRST - Low Power reset. - * - * @return FlagStatus - SET or RESET. - */ -FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG) -{ - uint32_t tmp = 0; - uint32_t statusreg = 0; - - FlagStatus bitstatus = RESET; - tmp = RCC_FLAG >> 5; - - if (tmp == 1) - { - statusreg = RCC->CTLR; - } - else if (tmp == 2) - { - statusreg = RCC->BDCTLR; - } - else - { - statusreg = RCC->RSTSCKR; - } - - tmp = RCC_FLAG & FLAG_Mask; - - if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET) - { - bitstatus = SET; - } - else - { - bitstatus = RESET; - } - - return bitstatus; -} - -/********************************************************************* - * @fn RCC_ClearFlag - * - * @brief Clears the RCC reset flags. - * - * @return none - */ -void RCC_ClearFlag(void) -{ - RCC->RSTSCKR |= RSTSCKR_RMVF_Set; -} - -/********************************************************************* - * @fn RCC_GetITStatus - * - * @brief Checks whether the specified RCC interrupt has occurred or not. - * - * @param RCC_IT - specifies the RCC interrupt source to check. - * RCC_IT_LSIRDY - LSI ready interrupt. - * RCC_IT_LSERDY - LSE ready interrupt. - * RCC_IT_HSIRDY - HSI ready interrupt. - * RCC_IT_HSERDY - HSE ready interrupt. - * RCC_IT_PLLRDY - PLL ready interrupt. - * RCC_IT_PLL2RDY - PLL2 ready interrupt. - * RCC_IT_PLL3RDY - PLL3 ready interrupt. - * RCC_IT_CSS - Clock Security System interrupt. - * - * @return ITStatus - SET or RESET. - */ - -ITStatus RCC_GetITStatus(uint8_t RCC_IT) -{ - ITStatus bitstatus = RESET; - - if ((RCC->INTR & RCC_IT) != (uint32_t)RESET) - { - bitstatus = SET; - } - else - { - bitstatus = RESET; - } - - return bitstatus; -} - -/********************************************************************* - * @fn RCC_ClearITPendingBit - * - * @brief Clears the RCC's interrupt pending bits. - * - * @param RCC_IT - specifies the interrupt pending bit to clear. - * RCC_IT_LSIRDY - LSI ready interrupt. - * RCC_IT_LSERDY - LSE ready interrupt. - * RCC_IT_HSIRDY - HSI ready interrupt. - * RCC_IT_HSERDY - HSE ready interrupt. - * RCC_IT_PLLRDY - PLL ready interrupt. - * RCC_IT_PLL2RDY - PLL2 ready interrupt. - * RCC_IT_PLL3RDY - PLL3 ready interrupt. - * RCC_IT_CSS - Clock Security System interrupt. - * - * @return none - */ -void RCC_ClearITPendingBit(uint8_t RCC_IT) -{ - *(__IO uint8_t *) INTR_BYTE3_ADDRESS = RCC_IT; -} - -/********************************************************************* - * @fn RCC_PREDIV1Config - * - * @brief Configures the PREDIV1 division factor. - * - * @param RCC_PREDIV1_Source - specifies the PREDIV1 clock source. - * RCC_PREDIV1_Source_HSE - HSE selected as PREDIV1 clock - * RCC_PREDIV1_Source_PLL2 - PLL2 selected as PREDIV1 clock - * RCC_PREDIV1_Div - specifies the PREDIV1 clock division factor. - * This parameter can be RCC_PREDIV1_Divx where x[1,16] - * - * @return none - */ -void RCC_PREDIV1Config(uint32_t RCC_PREDIV1_Source, uint32_t RCC_PREDIV1_Div) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CFGR2; - tmpreg &= ~(CFGR2_PREDIV1 | CFGR2_PREDIV1SRC); - tmpreg |= RCC_PREDIV1_Source | RCC_PREDIV1_Div ; - RCC->CFGR2 = tmpreg; -} - -/********************************************************************* - * @fn RCC_PREDIV2Config - * - * @brief Configures the PREDIV2 division factor. - * - * @param RCC_PREDIV2_Div - specifies the PREDIV2 clock division factor. - * This parameter can be RCC_PREDIV2_Divx where x:[1,16] - * - * @return none - */ -void RCC_PREDIV2Config(uint32_t RCC_PREDIV2_Div) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CFGR2; - tmpreg &= ~CFGR2_PREDIV2; - tmpreg |= RCC_PREDIV2_Div; - RCC->CFGR2 = tmpreg; -} - -/********************************************************************* - * @fn RCC_PLL2Config - * - * @brief Configures the PLL2 multiplication factor. - * - * @param RCC_PLL2Mul - specifies the PLL2 multiplication factor. - * This parameter can be RCC_PLL2Mul_x where x:{[8,14], 16, 20} - * - * @return none - */ -void RCC_PLL2Config(uint32_t RCC_PLL2Mul) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CFGR2; - tmpreg &= ~CFGR2_PLL2MUL; - tmpreg |= RCC_PLL2Mul; - RCC->CFGR2 = tmpreg; -} - -/********************************************************************* - * @fn RCC_PLL2Cmd - * - * @brief Enables or disables the PLL2. - * - * @param NewState - new state of the PLL2. This parameter can be - * ENABLE or DISABLE. - * - * @return none - */ -void RCC_PLL2Cmd(FunctionalState NewState) -{ - if(NewState) - { - RCC->CTLR |= (1<<26); - } - else{ - RCC->CTLR &= ~(1<<26); - } -} - -/********************************************************************* - * @fn RCC_PLL3Config - * - * @brief Configures the PLL3 multiplication factor. - * - * @param RCC_PLL3Mul - specifies the PLL2 multiplication factor. - * This parameter can be RCC_PLL2Mul_x where x:{[8,14], 16, 20} - * - * @return none - */ -void RCC_PLL3Config(uint32_t RCC_PLL3Mul) -{ - uint32_t tmpreg = 0; - - tmpreg = RCC->CFGR2; - tmpreg &= ~CFGR2_PLL3MUL; - tmpreg |= RCC_PLL3Mul; - RCC->CFGR2 = tmpreg; -} - -/********************************************************************* - * @fn RCC_PLL3Cmd - * - * @brief Enables or disables the PLL3. - * - * @param NewState - new state of the PLL2. This parameter can be - * ENABLE or DISABLE. - * - * @return none - */ -void RCC_PLL3Cmd(FunctionalState NewState) -{ - if(NewState) - { - RCC->CTLR |= (1<<28); - } - else{ - RCC->CTLR &= ~(1<<28); - } -} - -/********************************************************************* - * @fn RCC_OTGFSCLKConfig - * - * @brief Configures the USB OTG FS clock (OTGFSCLK). - * - * @param RCC_OTGFSCLKSource - specifies the USB OTG FS clock source. - * RCC_OTGFSCLKSource_PLLCLK_Div1 - PLL clock divided by 1 - * selected as USB OTG FS clock source - * RCC_OTGFSCLKSource_PLLCLK_Div2 - PLL clock divided by 2 - * selected as USB OTG FS clock source - * RCC_OTGFSCLKSource_PLLCLK_Div3 - PLL clock divided by 3 - * selected as USB OTG FS clock source - * - * @return none - */ -void RCC_OTGFSCLKConfig(uint32_t RCC_OTGFSCLKSource) -{ - RCC->CFGR0 &= ~(3<<22); - RCC->CFGR0 |= RCC_OTGFSCLKSource<<22; -} - -/********************************************************************* - * @fn RCC_I2S2CLKConfig - * - * @brief Configures the I2S2 clock source(I2S2CLK). - * - * @param RCC_I2S2CLKSource - specifies the I2S2 clock source. - * RCC_I2S2CLKSource_SYSCLK - system clock selected as I2S2 clock entry - * RCC_I2S2CLKSource_PLL3_VCO - PLL3 VCO clock selected as I2S2 clock entry - * - * @return none - */ -void RCC_I2S2CLKConfig(uint32_t RCC_I2S2CLKSource) -{ - RCC->CFGR2 &= ~(1<<17); - RCC->CFGR2 |= RCC_I2S2CLKSource<<17; -} - -/********************************************************************* - * @fn RCC_I2S3CLKConfig - * - * @brief Configures the I2S3 clock source(I2S2CLK). - * - * @param RCC_I2S3CLKSource - specifies the I2S3 clock source. - * RCC_I2S3CLKSource_SYSCLK - system clock selected as I2S3 clock entry - * RCC_I2S3CLKSource_PLL3_VCO - PLL3 VCO clock selected as I2S3 clock entry - * - * @return none - */ -void RCC_I2S3CLKConfig(uint32_t RCC_I2S3CLKSource) -{ - RCC->CFGR2 &= ~(1<<18); - RCC->CFGR2 |= RCC_I2S3CLKSource<<18; -} - -/********************************************************************* - * @fn RCC_AHBPeriphResetCmd - * - * @brief Forces or releases AHB peripheral reset. - * - * @param RCC_AHBPeriph - specifies the AHB peripheral to reset. - * RCC_AHBPeriph_OTG_FS - * RCC_AHBPeriph_ETH_MAC - * NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_AHBPeriphResetCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) -{ - if (NewState != DISABLE) - { - RCC->AHBRSTR |= RCC_AHBPeriph; - } - else - { - RCC->AHBRSTR &= ~RCC_AHBPeriph; - } -} - -/********************************************************************* - * @fn RCC_ADCCLKADJcmd - * - * @brief Enable ADC clock duty cycle adjustment. - * - * @param NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_ADCCLKADJcmd(FunctionalState NewState) -{ - if (NewState != DISABLE) - { - RCC->CFGR0 |= (1<<31); - } - else - { - RCC->CFGR0 &= ~(1<<31); - } -} - -/********************************************************************* - * @fn RCC_RNGCLKConfig - * - * @brief Configures the RNG clock source. - * - * @param RCC_RNGCLKSource - specifies the RNG clock source. - * RCC_RNGCLKSource_SYSCLK - system clock selected as RNG clock entry - * RCC_RNGCLKSource_PLL3_VCO - PLL3 VCO clock selected as RNG clock entry - * - * @return none - */ -void RCC_RNGCLKConfig(uint32_t RCC_RNGCLKSource) -{ - RCC->CFGR2 &= ~(1<<19); - RCC->CFGR2 |= RCC_RNGCLKSource<<19; -} - -/********************************************************************* - * @fn RCC_ETH1GCLKConfig - * - * @brief Configures the ETH1G clock source. - * - * @param RCC_RNGCLKSource - specifies the ETH1G clock source. - * RCC_ETH1GCLKSource_PLL2_VCO - system clock selected as ETH1G clock entry - * RCC_ETH1GCLKSource_PLL3_VCO - PLL3 VCO clock selected as ETH1G clock entry - * RCC_ETH1GCLKSource_PB1_IN - GPIO PB1 input clock selected as ETH1G clock entry - * - * @return none - */ -void RCC_ETH1GCLKConfig(uint32_t RCC_ETH1GCLKSource) -{ - RCC->CFGR2 &= ~(3<<20); - RCC->CFGR2 |= RCC_ETH1GCLKSource<<20; -} - -/********************************************************************* - * @fn RCC_ETH1G_125Mcmd - * - * @brief Enable ETH1G 125M. - * - * @param NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_ETH1G_125Mcmd(FunctionalState NewState) -{ - if (NewState != DISABLE) - { - RCC->CFGR2 |= (1<<22); - } - else - { - RCC->CFGR2 &= ~(1<<22); - } -} - -/********************************************************************* - * @fn RCC_USBHSConfig - * - * @brief Configures the USBHS clock. - * - * @param RCC_USBHS - defines the USBHS clock divider. - * RCC_USBPLL_Div1 - USBHS clock = USBPLL. - * RCC_USBPLL_Div2 - USBHS clock = USBPLL/2. - * RCC_USBPLL_Div3 - USBHS clock = USBPLL/3. - * RCC_USBPLL_Div4 - USBHS clock = USBPLL/4. - * RCC_USBPLL_Div5 - USBHS clock = USBPLL/5. - * RCC_USBPLL_Div6 - USBHS clock = USBPLL/6. - * RCC_USBPLL_Div7 - USBHS clock = USBPLL/7. - * RCC_USBPLL_Div8 - USBHS clock = USBPLL/8. - * - * @return none - */ -void RCC_USBHSConfig(uint32_t RCC_USBHS) -{ - RCC->CFGR2 &= ~(7<<24); - RCC->CFGR2 |= RCC_USBHS<<24; -} - -/********************************************************************* - * @fn RCC_USBHSPLLCLKConfig - * - * @brief Configures the USBHSPLL clock source. - * - * @param RCC_HSBHSPLLCLKSource - specifies the USBHSPLL clock source. - * RCC_HSBHSPLLCLKSource_HSE - HSE clock selected as USBHSPLL clock entry - * RCC_HSBHSPLLCLKSource_HSI - HSI clock selected as USBHSPLL clock entry - * - * @return none - */ -void RCC_USBHSPLLCLKConfig(uint32_t RCC_USBHSPLLCLKSource) -{ - RCC->CFGR2 &= ~(1<<27); - RCC->CFGR2 |= RCC_USBHSPLLCLKSource<<27; -} - -/********************************************************************* - * @fn RCC_USBHSPLLCKREFCLKConfig - * - * @brief Configures the USBHSPLL reference clock. - * - * @param RCC_USBHSPLLCKREFCLKSource - Select reference clock. - * RCC_USBHSPLLCKREFCLK_3M - reference clock 3Mhz. - * RCC_USBHSPLLCKREFCLK_4M - reference clock 4Mhz. - * RCC_USBHSPLLCKREFCLK_8M - reference clock 8Mhz. - * RCC_USBHSPLLCKREFCLK_5M - reference clock 5Mhz. - * - * @return none - */ -void RCC_USBHSPLLCKREFCLKConfig(uint32_t RCC_USBHSPLLCKREFCLKSource) -{ - RCC->CFGR2 &= ~(3<<28); - RCC->CFGR2 |= RCC_USBHSPLLCKREFCLKSource<<28; -} - -/********************************************************************* - * @fn RCC_USBHSPHYPLLALIVEcmd - * - * @brief Enable USBHS PHY control. - * - * @param NewState - ENABLE or DISABLE. - * - * @return none - */ -void RCC_USBHSPHYPLLALIVEcmd(FunctionalState NewState) -{ - if (NewState != DISABLE) - { - RCC->CFGR2 |= (1<<30); - } - else - { - RCC->CFGR2 &= ~(1<<30); - } -} - -/********************************************************************* - * @fn RCC_USBCLK48MConfig - * - * @brief Configures the USB clock 48MHz source. - * - * @param RCC_USBCLK48MSource - specifies the USB clock 48MHz source. - * RCC_USBCLK48MCLKSource_PLLCLK - PLLCLK clock selected as USB clock 48MHz clock entry - * RCC_USBCLK48MCLKSource_USBPHY - USBPHY clock selected as USB clock 48MHz clock entry - * - * @return none - */ -void RCC_USBCLK48MConfig(uint32_t RCC_USBCLK48MSource) -{ - RCC->CFGR2 &= ~(1<<31); - RCC->CFGR2 |= RCC_USBCLK48MSource<<31; -} diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.project b/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.project deleted file mode 100644 index 25be4dbc..00000000 --- a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.project +++ /dev/null @@ -1,79 +0,0 @@ - - - usb_stack_cdc_acm - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - - - Core - 2 - PARENT-4-PROJECT_LOC/SRC/Core - - - Debug - 2 - PARENT-4-PROJECT_LOC/SRC/Debug - - - Ld - 2 - PARENT-4-PROJECT_LOC/SRC/Ld - - - Peripheral - 2 - PARENT-4-PROJECT_LOC/SRC/Peripheral - - - Startup - 2 - PARENT-4-PROJECT_LOC/SRC/Startup - - - USB_Stack - 2 - PARENT-7-PROJECT_LOC - - - User - 2 - PROJECT_LOC/User - - - usb_stack - 2 - C:/Users/lvjiazhen/Desktop/usb_stack - - - - - 1595986042669 - - 22 - - org.eclipse.ui.ide.multiFilter - 1.0-name-matches-false-false-*.wvproj - - - - diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.settings/org.eclipse.core.resources.prefs b/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index cd7dddfa..00000000 --- a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding//usb_stack/port/ch32/usb_ch32_usbhs_reg.h=UTF-8 diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.template b/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.template deleted file mode 100644 index ed6fc0b4..00000000 --- a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.template +++ /dev/null @@ -1,13 +0,0 @@ - -Vendor=WCH -Link=WCH-Link -Toolchain= -Series= -Description= -Mcu Type=CH32V30x -Address=0x08000000 -Erase All=true -Program=true -Verify=true -Reset=true -Target Path=obj/usb_stack_cdc_acm.hex diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/USB_Stack_CDC_ACM.wvproj b/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/USB_Stack_CDC_ACM.wvproj deleted file mode 100644 index 2cd99d98..00000000 --- a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/USB_Stack_CDC_ACM.wvproj +++ /dev/null @@ -1,2 +0,0 @@ -iCZ ?"ǁrF<.ſ?/XOĿChQN$*EBk!2t+buhnUb]xll| -+"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 diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.cproject b/demo/ch32/usb_device/CH32V307VCT6/.cproject similarity index 67% rename from demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.cproject rename to demo/ch32/usb_device/CH32V307VCT6/.cproject index b8bee5ab..2701cc3b 100644 --- a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.cproject +++ b/demo/ch32/usb_device/CH32V307VCT6/.cproject @@ -57,14 +57,13 @@ - - - - - + diff --git a/demo/ch32/usb_device/CH32V307VCT6/.launch b/demo/ch32/usb_device/CH32V307VCT6/.launch new file mode 100644 index 00000000..43e84c52 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/.launch @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/.project b/demo/ch32/usb_device/CH32V307VCT6/.project new file mode 100644 index 00000000..41ae0c9e --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/.project @@ -0,0 +1,37 @@ + + + CH32V307VCT6 + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + 1595986042669 + + 22 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-*.wvproj + + + + diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.settings/language.settings.xml b/demo/ch32/usb_device/CH32V307VCT6/.settings/language.settings.xml similarity index 94% rename from demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.settings/language.settings.xml rename to demo/ch32/usb_device/CH32V307VCT6/.settings/language.settings.xml index 72fc3e4f..e80b501b 100644 --- a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/.settings/language.settings.xml +++ b/demo/ch32/usb_device/CH32V307VCT6/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/demo/ch32/usb_device/CH32V307VCT6/.template b/demo/ch32/usb_device/CH32V307VCT6/.template new file mode 100644 index 00000000..113ad030 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/.template @@ -0,0 +1,15 @@ +Mcu Type=CH32V30x +Address=0x08000000 +Erase All=true +Program=true +Verify=true +Reset=true + +Vendor=WCH +Link=WCH-Link +Toolchain=RISC-V +Series=CH32V307 +Description=ROM(byte): 256K, SRAM(byte): 64K, CHIP PINS: 100, GPIO PORTS: 80.\nWCH CH32V3 series of mainstream MCUs covers the needs of a large variety of applications in the industrial,medical and consumer markets. High performance with first-class peripherals and low-power,low-voltage operation is paired with a high level of integration at accessible prices with a simple architecture and easy-to-use tools. + +PeripheralVersion=1.5 +Target Path=obj\CH32V307VCT6.hex diff --git a/demo/ch32/usb_device/CH32V307VCT6/CH32V307VCT6.wvproj b/demo/ch32/usb_device/CH32V307VCT6/CH32V307VCT6.wvproj new file mode 100644 index 0000000000000000000000000000000000000000..b2d702ff3f6459cd4ebcfaca0188ca7731e16e6d GIT binary patch literal 202 zcmV;*05$)!C>RuNEtSZrcBu_3CkerIDQB6x-)wX-R}h7Ut*z@Z+Tr@ne+uDnWC zmkNDxMtKw13: Reserved */ + +/* Format Type Codes */ + +#define AUDIO_FORMAT_TYPE_UNDEF 0x00 +#define AUDIO_FORMAT_TYPEI 0x01 +#define AUDIO_FORMAT_TYPEII 0x02 +#define AUDIO_FORMAT_TYPEIII 0x03 +#define AUDIO_FORMAT_TYPEIV 0x04 +#define AUDIO_FORMAT_EXT_TYPEI 0x81 +#define AUDIO_FORMAT_EXT_TYPEII 0x82 +#define AUDIO_FORMAT_EXT_TYPEIII 0x83 + +/* Audio Data Format Type I Bit Allocations */ + +#define AUDIO_FORMAT_TYPEI_PCM (1 << 0) +#define AUDIO_FORMAT_TYPEI_PCM8 (1 << 1) +#define AUDIO_FORMAT_TYPEI_IEEEFLOAT (1 << 2) +#define AUDIO_FORMAT_TYPEI_ALAW (1 << 3) +#define AUDIO_FORMAT_TYPEI_MULAW (1 << 4) +#define AUDIO_FORMAT_TYPEI_RAWDATA (1 << 31) + +/* Audio Data Format Type II Bit Allocations */ + +#define AUDIO_FORMAT_TYPEII_MPEG (1 << 0) +#define AUDIO_FORMAT_TYPEII_AC3 (1 << 1) +#define AUDIO_FORMAT_TYPEII_WMA (1 << 2) +#define AUDIO_FORMAT_TYPEII_DTS (1 << 3) +#define AUDIO_FORMAT_TYPEII_RAWDATA (1 << 31) + +/* Audio Data Format Type III Bit Allocations */ + +#define AUDIO_FORMAT_TYPEIII_IEC61937_AC3 (1 << 0) +#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG1_L1 (1 << 1) +#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG1_L2_3 (1 << 1) +#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG2_NOEXT (1 << 2) +#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG2_EXT (1 << 3) +#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG2_AAC_ADTS (1 << 4) +#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG2_L1_LS (1 << 5) +#define AUDIO_FORMAT_TYPEIII_IEC61937_MPEG2_L2_3_LS (1 << 6) +#define AUDIO_FORMAT_TYPEIII_IEC61937_DTS_I (1 << 7) +#define AUDIO_FORMAT_TYPEIII_IEC61937_DTS_II (1 << 8) +#define AUDIO_FORMAT_TYPEIII_IEC61937_DTS_III (1 << 9) +#define AUDIO_FORMAT_TYPEIII_IEC61937_ATRAC (1 << 10) +#define AUDIO_FORMAT_TYPEIII_IEC61937_ATRAC2_3 (1 << 11) +#define AUDIO_FORMAT_TYPEIII_WMA (1 << 12) + +/* Audio Data Format Type IV Bit Allocations */ + +#define AUDIO_FORMAT_TYPEIV_PCM (1 << 0) +#define AUDIO_FORMAT_TYPEIV_PCM8 (1 << 1) +#define AUDIO_FORMAT_TYPEIV_IEEE_FLOAT (1 << 2) +#define AUDIO_FORMAT_TYPEIV_ALAW (1 << 3) +#define AUDIO_FORMAT_TYPEIV_MULAW (1 << 4) +#define AUDIO_FORMAT_TYPEIV_MPEG (1 << 5) +#define AUDIO_FORMAT_TYPEIV_AC3 (1 << 6) +#define AUDIO_FORMAT_TYPEIV_WMA (1 << 7) +#define AUDIO_FORMAT_TYPEIV_IEC61937_AC3 (1 << 8) +#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG1_L1 (1 << 9) +#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG1_L2_3 (1 << 10) +#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG2_NOEXT (1 << 10) +#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG2_EXT (1 << 11) +#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG2_AAC_ADTS (1 << 12) +#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG2_L1_LS (1 << 13) +#define AUDIO_FORMAT_TYPEIV_IEC61937_MPEG2_L2_3_LS (1 << 14) +#define AUDIO_FORMAT_TYPEIV_IEC61937_DTS_I (1 << 15) +#define AUDIO_FORMAT_TYPEIV_IEC61937_DTS_II (1 << 16) +#define AUDIO_FORMAT_TYPEIV_IEC61937_DTS_III (1 << 17) +#define AUDIO_FORMAT_TYPEIV_IEC61937_ATRAC (1 << 18) +#define AUDIO_FORMAT_TYPEIV_IEC61937_ATRAC2_3 (1 << 19) +#define AUDIO_FORMAT_TYPEIV_TYPE_III_WMA (1 << 20) +#define AUDIO_FORMAT_TYPEIV_IEC60958_PCM (1 << 21) + +/* Side Band Protocol Codes */ +#define AUDIO_SIDEBAND_PROTOCOL_UNDEF 0x00 +#define AUDIO_PRES_TIMESTAMP_PROTOCOL 0x01 + +/* USB Terminal Types */ +#define AUDIO_TERMINAL_UNDEF 0x0100 +#define AUDIO_TERMINAL_STREAMING 0x0101 +#define AUDIO_TERMINAL_VENDOR 0x01ff + +/* Input Terminal Types */ +#define AUDIO_INTERM_UNDEF 0x0200 /* Undefined Type */ +#define AUDIO_INTERM_MIC 0x0201 /* A generic microhpone */ +#define AUDIO_INTERM_DESKTOP_MIC 0x0202 /* A desktop microphone */ +#define AUDIO_INTERM_PERSONAL_MIC 0x0203 /* Head-mounted or clip-on microphone */ +#define AUDIO_INTERM_OMNI_MIC 0x0204 /* Omni-directional microphone */ +#define AUDIO_INTERM_MIC_ARRAY 0x0205 /* Microphone array */ +#define AUDIO_INTERM_PROC_MIC_ARRAY 0x0206 /* Microphone array with signal processor */ + +/* Output Terminal Types */ +#define AUDIO_OUTTERM_UNDEF 0x0300 /* Undefined Type */ +#define AUDIO_OUTTERM_SPEAKER 0x0301 /* Generic speakers */ +#define AUDIO_OUTTERM_HEADPHONES 0x0302 /* A head-mounted audio output device */ +#define AUDIO_OUTTERM_HEADDISPLAY 0x0303 /* Head Mounted Display Audio */ +#define AUDIO_OUTTERM_DESKTOP 0x0304 /* Desktop speaker */ +#define AUDIO_OUTTERM_ROOM 0x0305 /* Room speaker */ +#define AUDIO_OUTTERM_COMMS 0x0306 /* Communication speaker */ +#define AUDIO_OUTTERM_LOFREQ 0x0307 /* Low frequency effects speaker */ + +/* Bi-directional Terminal Types */ +#define AUDIO_BIDITERM_UNDEF 0x0400 /* Undefined Type */ +#define AUDIO_BIDITERM_HANDSET 0x0401 /* Hand-held bi-directional audio device */ +#define AUDIO_BIDITERM_HEADSET 0x0402 /* Head-mounted bi-directional audio device */ +#define AUDIO_BIDITERM_SPEAKERPHONE 0x0403 /* Speakerphone, no echo reduction */ +#define AUDIO_BIDITERM_ECHOSUPPRESS 0x0404 /* Echo-suppressing speakerphone */ +#define AUDIO_BIDITERM_ECHOCANCEL 0x0405 /* Echo-canceling speakerphone */ + +/* Telephony Terminal Types */ +#define AUDIO_TELETERM_UNDEF 0x0500 /* Undefined Type */ +#define AUDIO_TELETERM_PHONELINE 0x0501 /* Analog telephone line jack, an ISDN line, + * a proprietary PBX interface, or a wireless link */ +#define AUDIO_TELETERM_TELEPHONE 0x0502 /* Device can be used as a telephone */ +#define AUDIO_TELETERM_DOWNLINE 0x0503 /* Down Line Phone */ + +/* External Terminal Types */ +#define AUDIO_EXTTERM_UNDEF 0x0600 /* Undefined Type */ +#define AUDIO_EXTTERM_ANALOG 0x0601 /* Generic analog connector */ +#define AUDIO_EXTTERM_DIGITAL 0x0602 /* Generic digital audio interface */ +#define AUDIO_EXTTERM_LINE 0x0603 /* Analog connector at standard line levels */ +#define AUDIO_EXTTERM_LEGACY 0x0604 /* Legacy audio line out connector */ +#define AUDIO_EXTTERM_SPDIF 0x0605 /* SPDIF interface */ +#define AUDIO_EXTTERM_1394DA 0x0606 /* 1394 DA stream */ +#define AUDIO_EXTTERM_1394DV 0x0607 /* 1394 DV stream soundtrack */ +#define AUDIO_EXTTERM_ADAT 0x0608 /* ADAT Lightpipe */ +#define AUDIO_EXTTERM_TDIF 0x0609 /* TDIF - Tascam Digital Interface */ +#define AUDIO_EXTTERM_MADI 0x060a /* MADI - Multi-channel Audio Digital Interface (AES) */ + +/* Embedded Function Terminal Types */ +#define AUDIO_EMBEDTERM_UNDEF 0x0700 /* Undefined Type */ +#define AUDIO_EMBEDTERM_CALIBRATION 0x0701 /* Level Calibration Noise Source */ +#define AUDIO_EMBEDTERM_EQUALIZATION 0x0702 /* Equalization Noise */ +#define AUDIO_EMBEDTERM_CD 0x0703 /* CD player */ +#define AUDIO_EMBEDTERM_DAT 0x0704 /* Digital Audio Tape */ +#define AUDIO_EMBEDTERM_DCC 0x0705 /* Digital Compact Cassette */ +#define AUDIO_EMBEDTERM_COMPRESSED 0x0706 /* Compressed Audio Player */ +#define AUDIO_EMBEDTERM_TAPE 0x0707 /* Analog Audio Tape */ +#define AUDIO_EMBEDTERM_PHONOGRAPH 0x0708 /* Analog vinyl record player */ +#define AUDIO_EMBEDTERM_VCR 0x0709 /* Audio track of VCR */ +#define AUDIO_EMBEDTERM_VIDDISC 0x070a /* Audio track of VideoDisc player */ +#define AUDIO_EMBEDTERM_DVD 0x070b /* Audio track of DVD player */ +#define AUDIO_EMBEDTERM_TVTUNER 0x070c /* Audio track of TV tuner */ +#define AUDIO_EMBEDTERM_SATELLITE 0x070d /* Audio track of satellite receiver */ +#define AUDIO_EMBEDTERM_CABLETUNER 0x070e /* Audio track of cable tuner */ +#define AUDIO_EMBEDTERM_DSS 0x070f /* Audio track of DSS receiver */ +#define AUDIO_EMBEDTERM_RADIO 0x0710 /* AM/FM radio receiver */ +#define AUDIO_EMBEDTERM_TRANSMITTER 0x0711 /* AM/FM radio transmitter */ +#define AUDIO_EMBEDTERM_MULTITRACK 0x0712 /* A multi-track recording system */ +#define AUDIO_EMBEDTERM_SYNTHESIZER 0x0713 /* Synthesizer */ +#define AUDIO_EMBEDTERM_PIANO 0x0714 /* Piano */ +#define AUDIO_EMBEDTERM_GUITAR 0x0715 /* Guitar */ +#define AUDIO_EMBEDTERM_PERCUSSON 0x0716 /* Percussion Instrument */ +#define AUDIO_EMBEDTERM_INSTRUMENT 0x0717 /* Other Musical Instrument */ + +#define AUDIO_FORMAT_TYPE_I 0x01 +#define AUDIO_FORMAT_TYPE_II 0x02 +#define AUDIO_FORMAT_TYPE_III 0x03 + +/** USB Terminal Types + * Refer to Table 2-1 - Table 2-4 from termt10.pdf + */ +enum usb_audio_terminal_types { + /* USB Terminal Types */ + USB_AUDIO_USB_UNDEFINED = 0x0100, + USB_AUDIO_USB_STREAMING = 0x0101, + USB_AUDIO_USB_VENDOR_SPEC = 0x01FF, + + /* Input Terminal Types */ + USB_AUDIO_IN_UNDEFINED = 0x0200, + USB_AUDIO_IN_MICROPHONE = 0x0201, + USB_AUDIO_IN_DESKTOP_MIC = 0x0202, + USB_AUDIO_IN_PERSONAL_MIC = 0x0203, + USB_AUDIO_IN_OM_DIR_MIC = 0x0204, + USB_AUDIO_IN_MIC_ARRAY = 0x0205, + USB_AUDIO_IN_PROC_MIC_ARRAY = 0x0205, + + /* Output Terminal Types */ + USB_AUDIO_OUT_UNDEFINED = 0x0300, + USB_AUDIO_OUT_SPEAKER = 0x0301, + USB_AUDIO_OUT_HEADPHONES = 0x0302, + USB_AUDIO_OUT_HEAD_AUDIO = 0x0303, + USB_AUDIO_OUT_DESKTOP_SPEAKER = 0x0304, + USB_AUDIO_OUT_ROOM_SPEAKER = 0x0305, + USB_AUDIO_OUT_COMM_SPEAKER = 0x0306, + USB_AUDIO_OUT_LOW_FREQ_SPEAKER = 0x0307, + + /* Bi-directional Terminal Types */ + USB_AUDIO_IO_UNDEFINED = 0x0400, + USB_AUDIO_IO_HANDSET = 0x0401, + USB_AUDIO_IO_HEADSET = 0x0402, + USB_AUDIO_IO_SPEAKERPHONE_ECHO_NONE = 0x0403, + USB_AUDIO_IO_SPEAKERPHONE_ECHO_SUP = 0x0404, + USB_AUDIO_IO_SPEAKERPHONE_ECHO_CAN = 0x0405, +}; + +/** + * @warning Size of baInterface is 2 just to make it useable + * for all kind of devices: headphones, microphone and headset. + * Actual size of the struct should be checked by reading + * .bLength. + */ +struct adc_ac_if_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint16_t bcdAUDIO; + uint16_t wTotalLength; + uint8_t bInCollection; + uint8_t baInterfaceNr[2]; +} __PACKED; + +struct adc_as_if_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bTerminalLink; + uint8_t bDelay; + uint16_t wFormatTag; +} __PACKED; + +struct adc_input_terminal_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bTerminalID; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t bNrChannels; + uint16_t wChannelConfig; + uint8_t iChannelNames; + uint8_t iTerminal; +} __PACKED; + +struct adc_output_terminal_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bTerminalID; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t bSourceID; + uint8_t iTerminal; +} __PACKED; + +/** + * @note Size of Feature unit descriptor is not fixed. + * This structure is just a helper not a common type. + */ +struct adc_feature_unit_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bUnitID; + uint8_t bSourceID; + uint8_t bControlSize; + uint16_t bmaControls[1]; +} __PACKED; + +struct adc_format_type_i_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bFormatType; + uint8_t bNrChannels; + uint8_t bSubframeSize; + uint8_t bBitResolution; + uint8_t bSamFreqType; + uint8_t tSamFreq[3]; +} __PACKED; + +struct adc_as_std_ep_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; + uint8_t bRefresh; + uint8_t bSynchAddress; +} __PACKED; + +struct adc_as_cs_ep_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmAttributes; + uint8_t bLockDelayUnits; + uint16_t wLockDelay; +} __PACKED; + +#endif /* _USB_AUDIO_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/audio/usbd_audio.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/audio/usbd_audio.c new file mode 100644 index 00000000..92c9a4c2 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/audio/usbd_audio.c @@ -0,0 +1,153 @@ +/** + * @file usbd_audio.c + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbd_core.h" +#include "usbd_audio.h" + +struct usbd_audio_control_info { + uint16_t vol_min; + uint16_t vol_max; + uint16_t vol_res; + uint16_t vol_current; + uint8_t mute; +} audio_control_info = { 0xdb00, 0x0000, 0x0100, 0xf600, 0 }; + +static int audio_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USB_LOG_DBG("AUDIO Class request: " + "bRequest 0x%02x\r\n", + setup->bRequest); + + switch (setup->bRequest) { + case AUDIO_REQUEST_SET_CUR: + + if (LO_BYTE(setup->wValue) == 0x01) { + if (HI_BYTE(setup->wValue) == AUDIO_FU_CONTROL_MUTE) { + memcpy(&audio_control_info.mute, *data, *len); + usbd_audio_set_mute(audio_control_info.mute); + } else if (HI_BYTE(setup->wValue) == AUDIO_FU_CONTROL_VOLUME) { + memcpy(&audio_control_info.vol_current, *data, *len); + int vol; + if (audio_control_info.vol_current == 0) { + vol = 100; + } else { + vol = (audio_control_info.vol_current - 0xDB00 + 1) * 100 / (0xFFFF - 0xDB00); + } + usbd_audio_set_volume(vol); + USB_LOG_INFO("current audio volume:%d\r\n", vol); + } + } + + break; + + case AUDIO_REQUEST_GET_CUR: + if (HI_BYTE(setup->wValue) == AUDIO_FU_CONTROL_MUTE) { + *data = (uint8_t *)&audio_control_info.mute; + *len = 1; + } else if (HI_BYTE(setup->wValue) == AUDIO_FU_CONTROL_VOLUME) { + *data = (uint8_t *)&audio_control_info.vol_current; + *len = 2; + } + + break; + + case AUDIO_REQUEST_SET_RES: + break; + + case AUDIO_REQUEST_SET_MEM: + break; + + case AUDIO_REQUEST_GET_MIN: + *data = (uint8_t *)&audio_control_info.vol_min; + *len = 2; + break; + + case AUDIO_REQUEST_GET_MAX: + *data = (uint8_t *)&audio_control_info.vol_max; + *len = 2; + break; + + case AUDIO_REQUEST_GET_RES: + *data = (uint8_t *)&audio_control_info.vol_res; + *len = 2; + break; + case AUDIO_REQUEST_GET_MEM: + *data[0] = 0; + *len = 1; + break; + + default: + USB_LOG_WRN("Unhandled Audio Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + + return 0; +} + +static void audio_notify_handler(uint8_t event, void *arg) +{ + switch (event) { + case USBD_EVENT_RESET: + + break; + + case USBD_EVENT_SOF: + usbd_audio_sof_callback(); + break; + + case USBD_EVENT_SET_INTERFACE: + struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg; + usbd_audio_set_interface_callback(intf->bAlternateSetting); + break; + + default: + break; + } +} + +void usbd_audio_add_interface(usbd_class_t *devclass, usbd_interface_t *intf) +{ + static usbd_class_t *last_class = NULL; + + if (last_class != devclass) { + last_class = devclass; + usbd_class_register(devclass); + } + + intf->class_handler = audio_class_request_handler; + intf->custom_handler = NULL; + intf->vendor_handler = NULL; + intf->notify_handler = audio_notify_handler; + usbd_class_add_interface(devclass, intf); +} + +__WEAK void usbd_audio_set_volume(uint8_t vol) +{ +} + +__WEAK void usbd_audio_set_mute(uint8_t mute) +{ +} + +__WEAK void usbd_audio_sof_callback(void) +{ +} \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/audio/usbd_audio.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/audio/usbd_audio.h new file mode 100644 index 00000000..5eb32a79 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/audio/usbd_audio.h @@ -0,0 +1,43 @@ +/** + * @file usbd_audio.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBD_AUDIO_H_ +#define _USBD_AUDIO_H_ + +#include "usb_audio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void usbd_audio_add_interface(usbd_class_t *devclass, usbd_interface_t *intf); + +void usbd_audio_set_mute(uint8_t mute); +void usbd_audio_set_volume(uint8_t vol); +void usbd_audio_sof_callback(void); +void usbd_audio_set_interface_callback(uint8_t value); + +#ifdef __cplusplus +} +#endif + +#endif /* _USB_AUDIO_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usb_cdc.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usb_cdc.h new file mode 100644 index 00000000..0f131bbd --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usb_cdc.h @@ -0,0 +1,444 @@ +/** + * @file + * @brief USB Communications Device Class (CDC) public header + * + * Header follows the Class Definitions for + * Communications Devices Specification (CDC120-20101103-track.pdf), + * PSTN Devices Specification (PSTN120.pdf) and + * Ethernet Control Model Devices Specification (ECM120.pdf). + * Header is limited to ACM and ECM Subclasses. + */ + +#ifndef _USB_CDC_H +#define _USB_CDC_H + +/*------------------------------------------------------------------------------ + * Definitions based on usbcdc11.pdf (www.usb.org) + *----------------------------------------------------------------------------*/ +/* Communication device class specification version 1.10 */ +#define CDC_V1_10 0x0110U +// Communication device class specification version 1.2 +#define CDC_V1_2_0 0x0120U + +/* Communication interface class code */ +/* (usbcdc11.pdf, 4.2, Table 15) */ +#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02U + +/* Communication interface class subclass codes */ +/* (usbcdc11.pdf, 4.3, Table 16) */ +#define CDC_SUBCLASS_NONE 0x00 /* Reserved */ +#define CDC_SUBCLASS_DLC 0x01 /* Direct Line Control Model */ +#define CDC_SUBCLASS_ACM 0x02 /* Abstract Control Model */ +#define CDC_SUBCLASS_TCM 0x03 /* Telephone Control Model */ +#define CDC_SUBCLASS_MCM 0x04 /* Multi-Channel Control Model */ +#define CDC_SUBCLASS_CAPI 0x05 /* CAPI Control Model */ +#define CDC_SUBCLASS_ECM 0x06 /* Ethernet Networking Control Model */ +#define CDC_SUBCLASS_ATM 0x07 /* ATM Networking Control Model */ + /* 0x08-0x0d Reserved (future use) */ +#define CDC_SUBCLASS_MBIM 0x0e /* MBIM Control Model */ + /* 0x0f-0x7f Reserved (future use) */ + /* 0x80-0xfe Reserved (vendor specific) */ + +#define CDC_DIRECT_LINE_CONTROL_MODEL 0x01U +#define CDC_ABSTRACT_CONTROL_MODEL 0x02U +#define CDC_TELEPHONE_CONTROL_MODEL 0x03U +#define CDC_MULTI_CHANNEL_CONTROL_MODEL 0x04U +#define CDC_CAPI_CONTROL_MODEL 0x05U +#define CDC_ETHERNET_NETWORKING_CONTROL_MODEL 0x06U +#define CDC_ATM_NETWORKING_CONTROL_MODEL 0x07U +#define CDC_WIRELESS_HANDSET_CONTROL_MODEL 0x08U +#define CDC_DEVICE_MANAGEMENT 0x09U +#define CDC_MOBILE_DIRECT_LINE_MODEL 0x0AU +#define CDC_OBEX 0x0BU +#define CDC_ETHERNET_EMULATION_MODEL 0x0CU +#define CDC_NETWORK_CONTROL_MODEL 0x0DU + +/* Communication interface class control protocol codes */ +/* (usbcdc11.pdf, 4.4, Table 17) */ +#define CDC_COMMON_PROTOCOL_NONE 0x00U +#define CDC_COMMON_PROTOCOL_AT_COMMANDS 0x01U +#define CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101 0x02U +#define CDC_COMMON_PROTOCOL_AT_COMMANDS_PCCA_101_AND_ANNEXO 0x03U +#define CDC_COMMON_PROTOCOL_AT_COMMANDS_GSM_707 0x04U +#define CDC_COMMON_PROTOCOL_AT_COMMANDS_3GPP_27007 0x05U +#define CDC_COMMON_PROTOCOL_AT_COMMANDS_CDMA 0x06U +#define CDC_COMMON_PROTOCOL_ETHERNET_EMULATION_MODEL 0x07U +// NCM Communication Interface Protocol Codes +// (usbncm10.pdf, 4.2, Table 4-2) +#define CDC_NCM_PROTOCOL_NONE 0x00U +#define CDC_NCM_PROTOCOL_OEM 0xFEU + +/* Data interface class code */ +/* (usbcdc11.pdf, 4.5, Table 18) */ +#define CDC_DATA_INTERFACE_CLASS 0x0A + +/* Data Interface Sub-Class Codes ********************************************/ +#define CDC_DATA_SUBCLASS_NONE 0x00 + +/* Data interface class protocol codes */ +/* (usbcdc11.pdf, 4.7, Table 19) */ +#define CDC_DATA_PROTOCOL_ISDN_BRI 0x30 +#define CDC_DATA_PROTOCOL_HDLC 0x31 +#define CDC_DATA_PROTOCOL_TRANSPARENT 0x32 +#define CDC_DATA_PROTOCOL_Q921_MANAGEMENT 0x50 +#define CDC_DATA_PROTOCOL_Q921_DATA_LINK 0x51 +#define CDC_DATA_PROTOCOL_Q921_MULTIPLEXOR 0x52 +#define CDC_DATA_PROTOCOL_V42 0x90 +#define CDC_DATA_PROTOCOL_EURO_ISDN 0x91 +#define CDC_DATA_PROTOCOL_V24_RATE_ADAPTATION 0x92 +#define CDC_DATA_PROTOCOL_CAPI 0x93 +#define CDC_DATA_PROTOCOL_HOST_BASED_DRIVER 0xFD +#define CDC_DATA_PROTOCOL_DESCRIBED_IN_PUFD 0xFE + +/* Type values for bDescriptorType field of functional descriptors */ +/* (usbcdc11.pdf, 5.2.3, Table 24) */ +#define CDC_CS_INTERFACE 0x24 +#define CDC_CS_ENDPOINT 0x25 + +/* Type values for bDescriptorSubtype field of functional descriptors */ +/* (usbcdc11.pdf, 5.2.3, Table 25) */ +#define CDC_FUNC_DESC_HEADER 0x00 +#define CDC_FUNC_DESC_CALL_MANAGEMENT 0x01 +#define CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT 0x02 +#define CDC_FUNC_DESC_DIRECT_LINE_MANAGEMENT 0x03 +#define CDC_FUNC_DESC_TELEPHONE_RINGER 0x04 +#define CDC_FUNC_DESC_REPORTING_CAPABILITIES 0x05 +#define CDC_FUNC_DESC_UNION 0x06 +#define CDC_FUNC_DESC_COUNTRY_SELECTION 0x07 +#define CDC_FUNC_DESC_TELEPHONE_OPERATIONAL_MODES 0x08 +#define CDC_FUNC_DESC_USB_TERMINAL 0x09 +#define CDC_FUNC_DESC_NETWORK_CHANNEL 0x0A +#define CDC_FUNC_DESC_PROTOCOL_UNIT 0x0B +#define CDC_FUNC_DESC_EXTENSION_UNIT 0x0C +#define CDC_FUNC_DESC_MULTI_CHANNEL_MANAGEMENT 0x0D +#define CDC_FUNC_DESC_CAPI_CONTROL_MANAGEMENT 0x0E +#define CDC_FUNC_DESC_ETHERNET_NETWORKING 0x0F +#define CDC_FUNC_DESC_ATM_NETWORKING 0x10 +#define CDC_FUNC_DESC_WIRELESS_HANDSET_CONTROL_MODEL 0x11 +#define CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL 0x12 +#define CDC_FUNC_DESC_MOBILE_DIRECT_LINE_MODEL_DETAIL 0x13 +#define CDC_FUNC_DESC_DEVICE_MANAGEMENT_MODEL 0x14 +#define CDC_FUNC_DESC_OBEX 0x15 +#define CDC_FUNC_DESC_COMMAND_SET 0x16 +#define CDC_FUNC_DESC_COMMAND_SET_DETAIL 0x17 +#define CDC_FUNC_DESC_TELEPHONE_CONTROL_MODEL 0x18 +#define CDC_FUNC_DESC_OBEX_SERVICE_IDENTIFIER 0x19 + +/* CDC class-specific request codes */ +/* (usbcdc11.pdf, 6.2, Table 46) */ +/* see Table 45 for info about the specific requests. */ +#define CDC_REQUEST_SEND_ENCAPSULATED_COMMAND 0x00 +#define CDC_REQUEST_GET_ENCAPSULATED_RESPONSE 0x01 +#define CDC_REQUEST_SET_COMM_FEATURE 0x02 +#define CDC_REQUEST_GET_COMM_FEATURE 0x03 +#define CDC_REQUEST_CLEAR_COMM_FEATURE 0x04 +#define CDC_REQUEST_SET_AUX_LINE_STATE 0x10 +#define CDC_REQUEST_SET_HOOK_STATE 0x11 +#define CDC_REQUEST_PULSE_SETUP 0x12 +#define CDC_REQUEST_SEND_PULSE 0x13 +#define CDC_REQUEST_SET_PULSE_TIME 0x14 +#define CDC_REQUEST_RING_AUX_JACK 0x15 +#define CDC_REQUEST_SET_LINE_CODING 0x20 +#define CDC_REQUEST_GET_LINE_CODING 0x21 +#define CDC_REQUEST_SET_CONTROL_LINE_STATE 0x22 +#define CDC_REQUEST_SEND_BREAK 0x23 +#define CDC_REQUEST_SET_RINGER_PARMS 0x30 +#define CDC_REQUEST_GET_RINGER_PARMS 0x31 +#define CDC_REQUEST_SET_OPERATION_PARMS 0x32 +#define CDC_REQUEST_GET_OPERATION_PARMS 0x33 +#define CDC_REQUEST_SET_LINE_PARMS 0x34 +#define CDC_REQUEST_GET_LINE_PARMS 0x35 +#define CDC_REQUEST_DIAL_DIGITS 0x36 +#define CDC_REQUEST_SET_UNIT_PARAMETER 0x37 +#define CDC_REQUEST_GET_UNIT_PARAMETER 0x38 +#define CDC_REQUEST_CLEAR_UNIT_PARAMETER 0x39 +#define CDC_REQUEST_GET_PROFILE 0x3A +#define CDC_REQUEST_SET_ETHERNET_MULTICAST_FILTERS 0x40 +#define CDC_REQUEST_SET_ETHERNET_PMP_FILTER 0x41 +#define CDC_REQUEST_GET_ETHERNET_PMP_FILTER 0x42 +#define CDC_REQUEST_SET_ETHERNET_PACKET_FILTER 0x43 +#define CDC_REQUEST_GET_ETHERNET_STATISTIC 0x44 +#define CDC_REQUEST_SET_ATM_DATA_FORMAT 0x50 +#define CDC_REQUEST_GET_ATM_DEVICE_STATISTICS 0x51 +#define CDC_REQUEST_SET_ATM_DEFAULT_VC 0x52 +#define CDC_REQUEST_GET_ATM_VC_STATISTICS 0x53 + +/* Communication feature selector codes */ +/* (usbcdc11.pdf, 6.2.2..6.2.4, Table 47) */ +#define CDC_ABSTRACT_STATE 0x01 +#define CDC_COUNTRY_SETTING 0x02 + +/** Control Signal Bitmap Values for SetControlLineState */ +#define SET_CONTROL_LINE_STATE_RTS 0x02 +#define SET_CONTROL_LINE_STATE_DTR 0x01 + +/* Feature Status returned for ABSTRACT_STATE Selector */ +/* (usbcdc11.pdf, 6.2.3, Table 48) */ +#define CDC_IDLE_SETTING (1 << 0) +#define CDC_DATA_MULTPLEXED_STATE (1 << 1) + +/* Control signal bitmap values for the SetControlLineState request */ +/* (usbcdc11.pdf, 6.2.14, Table 51) */ +#define CDC_DTE_PRESENT (1 << 0) +#define CDC_ACTIVATE_CARRIER (1 << 1) + +/* CDC class-specific notification codes */ +/* (usbcdc11.pdf, 6.3, Table 68) */ +/* see Table 67 for Info about class-specific notifications */ +#define CDC_NOTIFICATION_NETWORK_CONNECTION 0x00 +#define CDC_RESPONSE_AVAILABLE 0x01 +#define CDC_AUX_JACK_HOOK_STATE 0x08 +#define CDC_RING_DETECT 0x09 +#define CDC_NOTIFICATION_SERIAL_STATE 0x20 +#define CDC_CALL_STATE_CHANGE 0x28 +#define CDC_LINE_STATE_CHANGE 0x29 +#define CDC_CONNECTION_SPEED_CHANGE 0x2A + +/* UART state bitmap values (Serial state notification). */ +/* (usbcdc11.pdf, 6.3.5, Table 69) */ +#define CDC_SERIAL_STATE_OVERRUN (1 << 6) /* receive data overrun error has occurred */ +#define CDC_SERIAL_STATE_OVERRUN_Pos (6) +#define CDC_SERIAL_STATE_OVERRUN_Msk (1 << CDC_SERIAL_STATE_OVERRUN_Pos) +#define CDC_SERIAL_STATE_PARITY (1 << 5) /* parity error has occurred */ +#define CDC_SERIAL_STATE_PARITY_Pos (5) +#define CDC_SERIAL_STATE_PARITY_Msk (1 << CDC_SERIAL_STATE_PARITY_Pos) +#define CDC_SERIAL_STATE_FRAMING (1 << 4) /* framing error has occurred */ +#define CDC_SERIAL_STATE_FRAMING_Pos (4) +#define CDC_SERIAL_STATE_FRAMING_Msk (1 << CDC_SERIAL_STATE_FRAMING_Pos) +#define CDC_SERIAL_STATE_RING (1 << 3) /* state of ring signal detection */ +#define CDC_SERIAL_STATE_RING_Pos (3) +#define CDC_SERIAL_STATE_RING_Msk (1 << CDC_SERIAL_STATE_RING_Pos) +#define CDC_SERIAL_STATE_BREAK (1 << 2) /* state of break detection */ +#define CDC_SERIAL_STATE_BREAK_Pos (2) +#define CDC_SERIAL_STATE_BREAK_Msk (1 << CDC_SERIAL_STATE_BREAK_Pos) +#define CDC_SERIAL_STATE_TX_CARRIER (1 << 1) /* state of transmission carrier */ +#define CDC_SERIAL_STATE_TX_CARRIER_Pos (1) +#define CDC_SERIAL_STATE_TX_CARRIER_Msk (1 << CDC_SERIAL_STATE_TX_CARRIER_Pos) +#define CDC_SERIAL_STATE_RX_CARRIER (1 << 0) /* state of receiver carrier */ +#define CDC_SERIAL_STATE_RX_CARRIER_Pos (0) +#define CDC_SERIAL_STATE_RX_CARRIER_Msk (1 << CDC_SERIAL_STATE_RX_CARRIER_Pos) + +/*------------------------------------------------------------------------------ + * Structures based on usbcdc11.pdf (www.usb.org) + *----------------------------------------------------------------------------*/ + +/* Header functional descriptor */ +/* (usbcdc11.pdf, 5.2.3.1) */ +/* This header must precede any list of class-specific descriptors. */ +struct cdc_header_descriptor { + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* Header functional descriptor subtype */ + uint16_t bcdCDC; /* USB CDC specification release version */ +} __PACKED; + +/* Call management functional descriptor */ +/* (usbcdc11.pdf, 5.2.3.2) */ +/* Describes the processing of calls for the communication class interface. */ +struct cdc_call_management_descriptor { + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* call management functional descriptor subtype */ + uint8_t bmCapabilities; /* capabilities that this configuration supports */ + uint8_t bDataInterface; /* interface number of the data class interface used for call management (optional) */ +} __PACKED; + +/* Abstract control management functional descriptor */ +/* (usbcdc11.pdf, 5.2.3.3) */ +/* Describes the command supported by the communication interface class with the Abstract Control Model subclass code. */ +struct cdc_abstract_control_management_descriptor { + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* abstract control management functional descriptor subtype */ + uint8_t bmCapabilities; /* capabilities supported by this configuration */ +} __PACKED; + +/* Union functional descriptors */ +/* (usbcdc11.pdf, 5.2.3.8) */ +/* Describes the relationship between a group of interfaces that can be considered to form a functional unit. */ +struct cdc_union_descriptor { + uint8_t bFunctionLength; /* size of this descriptor in bytes */ + uint8_t bDescriptorType; /* CS_INTERFACE descriptor type */ + uint8_t bDescriptorSubtype; /* union functional descriptor subtype */ + uint8_t bMasterInterface; /* interface number designated as master */ +} __PACKED; + +/* Union functional descriptors with one slave interface */ +/* (usbcdc11.pdf, 5.2.3.8) */ +struct cdc_union_1slave_descriptor { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bControlInterface; + uint8_t bSubordinateInterface0; +} __PACKED; + +/* Line coding structure for GET_LINE_CODING / SET_LINE_CODING class requests*/ +/* Format of the data returned when a GetLineCoding request is received */ +/* (usbcdc11.pdf, 6.2.13) */ +struct cdc_line_coding { + uint32_t dwDTERate; /* Data terminal rate in bits per second */ + uint8_t bCharFormat; /* Number of stop bits */ + uint8_t bParityType; /* Parity bit type */ + uint8_t bDataBits; /* Number of data bits */ +} __PACKED; + +/** Data structure for the notification about SerialState */ +struct cdc_acm_notification { + uint8_t bmRequestType; + uint8_t bNotificationType; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + uint16_t data; +} __PACKED; + +/** Ethernet Networking Functional Descriptor */ +struct cdc_ecm_descriptor { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t iMACAddress; + uint32_t bmEthernetStatistics; + uint16_t wMaxSegmentSize; + uint16_t wNumberMCFilters; + uint8_t bNumberPowerFilters; +} __PACKED; + +/*Length of template descriptor: 66 bytes*/ +#define CDC_ACM_DESCRIPTOR_LEN (8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 7) +// clang-format off +#ifndef CONFIG_USB_HS +#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \ + /* Interface Associate */ \ + 0x08, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \ + bFirstInterface, /* bFirstInterface */ \ + 0x02, /* bInterfaceCount */ \ + USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \ + CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \ + CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \ + 0x00, /* iFunction */ \ + 0x09, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ + bFirstInterface, /* bInterfaceNumber */ \ + 0x00, /* bAlternateSetting */ \ + 0x01, /* bNumEndpoints */ \ + USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \ + CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \ + CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \ + str_idx, /* iInterface */ \ + 0x05, /* bLength */ \ + CDC_CS_INTERFACE, /* bDescriptorType */ \ + CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \ + WBVAL(CDC_V1_10), /* bcdCDC */ \ + 0x05, /* bLength */ \ + CDC_CS_INTERFACE, /* bDescriptorType */ \ + CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \ + bFirstInterface, /* bmCapabilities */ \ + (uint8_t)(bFirstInterface + 1), /* bDataInterface */ \ + 0x04, /* bLength */ \ + CDC_CS_INTERFACE, /* bDescriptorType */ \ + CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \ + 0x02, /* bmCapabilities */ \ + 0x05, /* bLength */ \ + CDC_CS_INTERFACE, /* bDescriptorType */ \ + CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \ + bFirstInterface, /* bMasterInterface */ \ + (uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + int_ep, /* bEndpointAddress */ \ + 0x03, /* bmAttributes */ \ + 0x40, 0x00, /* wMaxPacketSize */ \ + 0x00, /* bInterval */ \ + 0x09, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ + (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \ + 0x00, /* bAlternateSetting */ \ + 0x02, /* bNumEndpoints */ \ + CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \ + 0x00, /* bInterfaceSubClass */ \ + 0x00, /* bInterfaceProtocol */ \ + 0x00, /* iInterface */ \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + out_ep, /* bEndpointAddress */ \ + 0x02, /* bmAttributes */ \ + 0x40, 0x00, /* wMaxPacketSize */ \ + 0x00, /* bInterval */ \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + in_ep, /* bEndpointAddress */ \ + 0x02, /* bmAttributes */ \ + 0x40, 0x00, /* wMaxPacketSize */ \ + 0x00 /* bInterval */ +#else +#define CDC_ACM_DESCRIPTOR_INIT(bFirstInterface, int_ep, out_ep, in_ep, str_idx) \ + /* Interface Associate */ \ + 0x08, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \ + bFirstInterface, /* bFirstInterface */ \ + 0x02, /* bInterfaceCount */ \ + USB_DEVICE_CLASS_CDC, /* bFunctionClass */ \ + CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */ \ + CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bFunctionProtocol */ \ + 0x00, /* iFunction */ \ + 0x09, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ + bFirstInterface, /* bInterfaceNumber */ \ + 0x00, /* bAlternateSetting */ \ + 0x01, /* bNumEndpoints */ \ + USB_DEVICE_CLASS_CDC, /* bInterfaceClass */ \ + CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass */ \ + CDC_COMMON_PROTOCOL_AT_COMMANDS, /* bInterfaceProtocol */ \ + str_idx, /* iInterface */ \ + 0x05, /* bLength */ \ + CDC_CS_INTERFACE, /* bDescriptorType */ \ + CDC_FUNC_DESC_HEADER, /* bDescriptorSubtype */ \ + WBVAL(CDC_V1_10), /* bcdCDC */ \ + 0x05, /* bLength */ \ + CDC_CS_INTERFACE, /* bDescriptorType */ \ + CDC_FUNC_DESC_CALL_MANAGEMENT, /* bDescriptorSubtype */ \ + bFirstInterface, /* bmCapabilities */ \ + (uint8_t)(bFirstInterface + 1), /* bDataInterface */ \ + 0x04, /* bLength */ \ + CDC_CS_INTERFACE, /* bDescriptorType */ \ + CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype */ \ + 0x02, /* bmCapabilities */ \ + 0x05, /* bLength */ \ + CDC_CS_INTERFACE, /* bDescriptorType */ \ + CDC_FUNC_DESC_UNION, /* bDescriptorSubtype */ \ + bFirstInterface, /* bMasterInterface */ \ + (uint8_t)(bFirstInterface + 1), /* bSlaveInterface0 */ \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + int_ep, /* bEndpointAddress */ \ + 0x03, /* bmAttributes */ \ + 0x00, 0x02, /* wMaxPacketSize */ \ + 0x00, /* bInterval */ \ + 0x09, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ + (uint8_t)(bFirstInterface + 1), /* bInterfaceNumber */ \ + 0x00, /* bAlternateSetting */ \ + 0x02, /* bNumEndpoints */ \ + CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass */ \ + 0x00, /* bInterfaceSubClass */ \ + 0x00, /* bInterfaceProtocol */ \ + 0x00, /* iInterface */ \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + out_ep, /* bEndpointAddress */ \ + 0x02, /* bmAttributes */ \ + 0x00, 0x02, /* wMaxPacketSize */ \ + 0x00, /* bInterval */ \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + in_ep, /* bEndpointAddress */ \ + 0x02, /* bmAttributes */ \ + 0x00, 0x02, /* wMaxPacketSize */ \ + 0x00 /* bInterval */ +#endif +// clang-format on + +#endif /* USB_CDC_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbd_cdc.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbd_cdc.c new file mode 100644 index 00000000..707e6ac0 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbd_cdc.c @@ -0,0 +1,171 @@ +/** + * @file usbd_cdc.c + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbd_core.h" +#include "usbd_cdc.h" + +const char *stop_name[] = { "1", "1.5", "2" }; +const char *parity_name[] = { "N", "O", "E", "M", "S" }; + +/* Device data structure */ +struct cdc_acm_cfg_priv { + /* CDC ACM line coding properties. LE order */ + struct cdc_line_coding line_coding; + /* CDC ACM line state bitmap, DTE side */ + uint8_t line_state; + /* CDC ACM serial state bitmap, DCE side */ + uint8_t serial_state; + /* CDC ACM notification sent status */ + uint8_t notification_sent; + /* CDC ACM configured flag */ + bool configured; + /* CDC ACM suspended flag */ + bool suspended; + uint32_t uart_first_init_flag; + +} usbd_cdc_acm_cfg; + +static void usbd_cdc_acm_reset(void) +{ + usbd_cdc_acm_cfg.line_coding.dwDTERate = 2000000; + usbd_cdc_acm_cfg.line_coding.bDataBits = 8; + usbd_cdc_acm_cfg.line_coding.bParityType = 0; + usbd_cdc_acm_cfg.line_coding.bCharFormat = 0; + usbd_cdc_acm_cfg.configured = false; + usbd_cdc_acm_cfg.uart_first_init_flag = 0; +} + +/** + * @brief Handler called for Class requests not handled by the USB stack. + * + * @param setup Information about the request to execute. + * @param len Size of the buffer. + * @param data Buffer containing the request result. + * + * @return 0 on success, negative errno code on fail. + */ +static int cdc_acm_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USB_LOG_DBG("CDC Class request: " + "bRequest 0x%02x\r\n", + setup->bRequest); + + switch (setup->bRequest) { + case CDC_REQUEST_SET_LINE_CODING: + + /*******************************************************************************/ + /* Line Coding Structure */ + /*-----------------------------------------------------------------------------*/ + /* Offset | Field | Size | Value | Description */ + /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ + /* 4 | bCharFormat | 1 | Number | Stop bits */ + /* 0 - 1 Stop bit */ + /* 1 - 1.5 Stop bits */ + /* 2 - 2 Stop bits */ + /* 5 | bParityType | 1 | Number | Parity */ + /* 0 - None */ + /* 1 - Odd */ + /* 2 - Even */ + /* 3 - Mark */ + /* 4 - Space */ + /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ + /*******************************************************************************/ + if (usbd_cdc_acm_cfg.uart_first_init_flag == 0) { + usbd_cdc_acm_cfg.uart_first_init_flag = 1; + return 0; + } + + memcpy(&usbd_cdc_acm_cfg.line_coding, *data, sizeof(usbd_cdc_acm_cfg.line_coding)); + USB_LOG_DBG("CDC_SET_LINE_CODING <%d %d %s %s>\r\n", + usbd_cdc_acm_cfg.line_coding.dwDTERate, + usbd_cdc_acm_cfg.line_coding.bDataBits, + parity_name[usbd_cdc_acm_cfg.line_coding.bParityType], + stop_name[usbd_cdc_acm_cfg.line_coding.bCharFormat]); + usbd_cdc_acm_set_line_coding(usbd_cdc_acm_cfg.line_coding.dwDTERate, usbd_cdc_acm_cfg.line_coding.bDataBits, + usbd_cdc_acm_cfg.line_coding.bParityType, usbd_cdc_acm_cfg.line_coding.bCharFormat); + break; + + case CDC_REQUEST_SET_CONTROL_LINE_STATE: + usbd_cdc_acm_cfg.line_state = (uint8_t)setup->wValue; + bool dtr = (setup->wValue & 0x01); + bool rts = (setup->wValue & 0x02); + USB_LOG_DBG("DTR 0x%x,RTS 0x%x\r\n", + dtr, rts); + usbd_cdc_acm_set_dtr(dtr); + usbd_cdc_acm_set_rts(rts); + break; + + case CDC_REQUEST_GET_LINE_CODING: + *data = (uint8_t *)(&usbd_cdc_acm_cfg.line_coding); + *len = sizeof(usbd_cdc_acm_cfg.line_coding); + USB_LOG_DBG("CDC_GET_LINE_CODING %d %d %d %d\r\n", + usbd_cdc_acm_cfg.line_coding.dwDTERate, + usbd_cdc_acm_cfg.line_coding.bCharFormat, + usbd_cdc_acm_cfg.line_coding.bParityType, + usbd_cdc_acm_cfg.line_coding.bDataBits); + break; + + default: + USB_LOG_WRN("Unhandled CDC Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + + return 0; +} + +static void cdc_notify_handler(uint8_t event, void *arg) +{ + switch (event) { + case USBD_EVENT_RESET: + usbd_cdc_acm_reset(); + break; + + default: + break; + } +} + +void usbd_cdc_add_acm_interface(usbd_class_t *devclass, usbd_interface_t *intf) +{ + static usbd_class_t *last_class = NULL; + + if (last_class != devclass) { + last_class = devclass; + usbd_class_register(devclass); + } + + intf->class_handler = cdc_acm_class_request_handler; + intf->custom_handler = NULL; + intf->vendor_handler = NULL; + intf->notify_handler = cdc_notify_handler; + usbd_class_add_interface(devclass, intf); +} + +__WEAK void usbd_cdc_acm_set_line_coding(uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits) +{ +} +__WEAK void usbd_cdc_acm_set_dtr(bool dtr) +{ +} +__WEAK void usbd_cdc_acm_set_rts(bool rts) +{ +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbd_cdc.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbd_cdc.h new file mode 100644 index 00000000..707e15eb --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbd_cdc.h @@ -0,0 +1,42 @@ +/** + * @file usbd_cdc.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBD_CDC_H +#define _USBD_CDC_H + +#include "usb_cdc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void usbd_cdc_add_acm_interface(usbd_class_t *devclass, usbd_interface_t *intf); + +void usbd_cdc_acm_set_line_coding(uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits); +void usbd_cdc_acm_set_dtr(bool dtr); +void usbd_cdc_acm_set_rts(bool rts); + +#ifdef __cplusplus +} +#endif + +#endif /* USBD_CDC_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbh_cdc_acm.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbh_cdc_acm.c new file mode 100644 index 00000000..32ac41d9 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbh_cdc_acm.c @@ -0,0 +1,343 @@ +/** + * @file usbh_cdc_acm.c + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbh_core.h" +#include "usbh_cdc_acm.h" + +#define DEV_FORMAT "/dev/ttyACM%d" +#define DEV_NAMELEN 16 + +static uint32_t g_devinuse = 0; + +/**************************************************************************** + * Name: usbh_cdc_acm_devno_alloc + * + * Description: + * Allocate a unique /dev/ttyACM[n] minor number in the range 0-31. + * + ****************************************************************************/ + +static int usbh_cdc_acm_devno_alloc(struct usbh_cdc_acm *priv) +{ + uint32_t flags; + int devno; + + flags = usb_osal_enter_critical_section(); + for (devno = 0; devno < 32; devno++) { + uint32_t bitno = 1 << devno; + if ((g_devinuse & bitno) == 0) { + g_devinuse |= bitno; + priv->minor = devno; + usb_osal_leave_critical_section(flags); + return 0; + } + } + + usb_osal_leave_critical_section(flags); + return -EMFILE; +} + +/**************************************************************************** + * Name: usbh_cdc_acm_devno_free + * + * Description: + * Free a /dev/ttyACM[n] minor number so that it can be used. + * + ****************************************************************************/ + +static void usbh_cdc_acm_devno_free(struct usbh_cdc_acm *priv) +{ + int devno = priv->minor; + + if (devno >= 0 && devno < 32) { + uint32_t flags = usb_osal_enter_critical_section(); + g_devinuse &= ~(1 << devno); + usb_osal_leave_critical_section(flags); + } +} + +/**************************************************************************** + * Name: usbh_cdc_acm_mkdevname + * + * Description: + * Format a /dev/ttyACM[n] device name given a minor number. + * + ****************************************************************************/ + +static inline void usbh_cdc_acm_mkdevname(struct usbh_cdc_acm *priv, char *devname) +{ + snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->minor); +} + +int usbh_cdc_acm_set_line_coding(struct usbh_hubport *hport, uint8_t intf, struct cdc_line_coding *line_coding) +{ + int ret; + struct usb_setup_packet *setup; + struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)hport->config.intf[intf].priv; + + setup = cdc_acm_class->setup; + + if (cdc_acm_class->ctrl_intf != intf) { + return -1; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = CDC_REQUEST_SET_LINE_CODING; + setup->wValue = 0; + setup->wIndex = intf; + setup->wLength = 7; + + ret = usbh_control_transfer(hport->ep0, setup, (uint8_t *)line_coding); + if (ret < 0) { + return ret; + } + memcpy(cdc_acm_class->linecoding, line_coding, sizeof(struct cdc_line_coding)); + return 0; +} + +int usbh_cdc_acm_get_line_coding(struct usbh_hubport *hport, uint8_t intf, struct cdc_line_coding *line_coding) +{ + int ret; + struct usb_setup_packet *setup; + struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)hport->config.intf[intf].priv; + + setup = cdc_acm_class->setup; + + if (cdc_acm_class->ctrl_intf != intf) { + return -1; + } + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = CDC_REQUEST_GET_LINE_CODING; + setup->wValue = 0; + setup->wIndex = intf; + setup->wLength = 7; + + ret = usbh_control_transfer(hport->ep0, setup, (uint8_t *)line_coding); + if (ret < 0) { + return ret; + } + memcpy(cdc_acm_class->linecoding, line_coding, sizeof(struct cdc_line_coding)); + return 0; +} + +int usbh_cdc_acm_set_line_state(struct usbh_hubport *hport, uint8_t intf, bool dtr, bool rts) +{ + int ret; + struct usb_setup_packet *setup; + struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)hport->config.intf[intf].priv; + + setup = cdc_acm_class->setup; + + if (cdc_acm_class->ctrl_intf != intf) { + return -1; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE; + setup->wValue = (dtr << 0) | (rts << 1); + setup->wIndex = intf; + setup->wLength = 0; + + ret = usbh_control_transfer(hport->ep0, setup, NULL); + if (ret < 0) { + return ret; + } + + cdc_acm_class->dtr = dtr; + cdc_acm_class->rts = rts; + + return 0; +} + +USB_NOCACHE_RAM_SECTION uint8_t cdc_buffer[4096]; + +void usbh_cdc_acm_callback(void *arg, int nbytes) +{ + struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)arg; + + if (nbytes > 0) { + for (size_t i = 0; i < nbytes; i++) { + printf("0x%02x ", cdc_buffer[i]); + } + } + + printf("nbytes:%d\r\n", nbytes); +} + +int usbh_cdc_acm_connect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usbh_endpoint_cfg ep_cfg = { 0 }; + struct usb_endpoint_descriptor *ep_desc; + char devname[DEV_NAMELEN]; + int ret; + + struct usbh_cdc_acm *cdc_acm_class = usb_malloc(sizeof(struct usbh_cdc_acm)); + if (cdc_acm_class == NULL) { + USB_LOG_ERR("Fail to alloc cdc_acm_class\r\n"); + return -ENOMEM; + } + + memset(cdc_acm_class, 0, sizeof(struct usbh_cdc_acm)); + + usbh_cdc_acm_devno_alloc(cdc_acm_class); + usbh_cdc_acm_mkdevname(cdc_acm_class, devname); + + hport->config.intf[intf].priv = cdc_acm_class; + hport->config.intf[intf + 1].priv = cdc_acm_class; + + cdc_acm_class->setup = usb_iomalloc(sizeof(struct usb_setup_packet)); + if (cdc_acm_class->setup == NULL) { + USB_LOG_ERR("Fail to alloc setup\r\n"); + return -ENOMEM; + } + cdc_acm_class->linecoding = usb_iomalloc(sizeof(struct cdc_line_coding)); + if (cdc_acm_class->linecoding == NULL) { + USB_LOG_ERR("Fail to alloc linecoding\r\n"); + return -ENOMEM; + } + cdc_acm_class->ctrl_intf = intf; + cdc_acm_class->data_intf = intf + 1; + + cdc_acm_class->linecoding->dwDTERate = 115200; + cdc_acm_class->linecoding->bDataBits = 8; + cdc_acm_class->linecoding->bParityType = 0; + cdc_acm_class->linecoding->bCharFormat = 0; + ret = usbh_cdc_acm_set_line_coding(hport, intf, cdc_acm_class->linecoding); + if (ret < 0) { + return ret; + } + + ret = usbh_cdc_acm_set_line_state(hport, intf, true, true); + if (ret < 0) { + return ret; + } + +#if 0 + ep_desc = &hport->config.intf[intf].ep[0].ep_desc; + ep_cfg.ep_addr = ep_desc->bEndpointAddress; + ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_interval = ep_desc->bInterval; + ep_cfg.hport = hport; + usbh_ep_alloc(&cdc_acm_class->intin, &ep_cfg); + +#endif + for (uint8_t i = 0; i < hport->config.intf[intf + 1].intf_desc.bNumEndpoints; i++) { + ep_desc = &hport->config.intf[intf + 1].ep[i].ep_desc; + + ep_cfg.ep_addr = ep_desc->bEndpointAddress; + ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_interval = ep_desc->bInterval; + ep_cfg.hport = hport; + if (ep_desc->bEndpointAddress & 0x80) { + usbh_ep_alloc(&cdc_acm_class->bulkin, &ep_cfg); + } else { + usbh_ep_alloc(&cdc_acm_class->bulkout, &ep_cfg); + } + } + + USB_LOG_INFO("Register CDC ACM Class:%s\r\n", devname); + + memset(cdc_buffer, 0, 512); + ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512); + if (ret < 0) { + printf("bulk in error\r\n"); + return ret; + } + printf("recv over:%d\r\n", ret); + for (size_t i = 0; i < ret; i++) { + printf("0x%02x ", cdc_buffer[i]); + } + printf("\r\n"); + const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 }; + + memcpy(cdc_buffer, data1, 8); + ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkout, cdc_buffer, 8); + if (ret < 0) { + printf("bulk out error\r\n"); + return ret; + } + printf("send over:%d\r\n", ret); + +#if 0 + usbh_ep_bulk_async_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, usbh_cdc_acm_callback, cdc_acm_class); +#else + ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512); + if (ret < 0) { + printf("bulk in error\r\n"); + return ret; + } + printf("recv over:%d\r\n", ret); + for (size_t i = 0; i < ret; i++) { + printf("0x%02x ", cdc_buffer[i]); + } + printf("\r\n"); +#endif + return ret; +} + +int usbh_cdc_acm_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + char devname[DEV_NAMELEN]; + int ret = 0; + + struct usbh_cdc_acm *cdc_acm_class = (struct usbh_cdc_acm *)hport->config.intf[intf].priv; + + if (cdc_acm_class) { + usbh_cdc_acm_devno_free(cdc_acm_class); + usbh_cdc_acm_mkdevname(cdc_acm_class, devname); + + if (cdc_acm_class->bulkin) { + ret = usb_ep_cancel(cdc_acm_class->bulkin); + if (ret < 0) { + } + usbh_ep_free(cdc_acm_class->bulkin); + } + + if (cdc_acm_class->bulkout) { + ret = usb_ep_cancel(cdc_acm_class->bulkout); + if (ret < 0) { + } + usbh_ep_free(cdc_acm_class->bulkout); + } + if (cdc_acm_class->setup) + usb_iofree(cdc_acm_class->setup); + if (cdc_acm_class->linecoding) + usb_iofree(cdc_acm_class->linecoding); + + usb_free(cdc_acm_class); + + hport->config.intf[intf].priv = NULL; + hport->config.intf[intf + 1].priv = NULL; + + USB_LOG_INFO("Unregister CDC ACM Class:%s\r\n", devname); + } + + return ret; +} + +const struct usbh_class_driver cdc_acm_class_driver = { + .driver_name = "cdc_acm", + .connect = usbh_cdc_acm_connect, + .disconnect = usbh_cdc_acm_disconnect +}; \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbh_cdc_acm.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbh_cdc_acm.h new file mode 100644 index 00000000..e1283504 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/cdc/usbh_cdc_acm.h @@ -0,0 +1,52 @@ +/** + * @file usbh_cdc_acm.h + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBH_CDC_ACM_H +#define _USBH_CDC_ACM_H + +#include "usb_cdc.h" + +struct usbh_cdc_acm { + struct usb_setup_packet *setup; + struct cdc_line_coding *linecoding; + uint8_t ctrl_intf; /* Control interface number */ + uint8_t data_intf; /* Data interface number */ + bool dtr; + bool rts; + uint8_t minor; + usbh_epinfo_t bulkin; /* Bulk IN endpoint */ + usbh_epinfo_t bulkout; /* Bulk OUT endpoint */ +#ifdef HAVE_INTIN_ENDPOINT + usbh_epinfo_t intin; /* Interrupt IN endpoint (optional) */ +#endif +}; + +extern const struct usbh_class_driver cdc_acm_class_driver; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usb_dfu.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usb_dfu.h new file mode 100644 index 00000000..937c2d55 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usb_dfu.h @@ -0,0 +1,103 @@ +/** + * @file + * @brief USB DFU Class public header + * + */ + +#ifndef _USB_DFU_H_ +#define _USB_DFU_H_ + +/**\addtogroup USB_MODULE_DFU USB DFU class + * \brief This module contains USB Device Firmware Upgrade class definitions. + * \details This module based on + * + [USB Device Firmware Upgrade Specification, Revision 1.1] + * (https://www.usb.org/sites/default/files/DFU_1.1.pdf) + * @{ */ + +/** DFU Specification release */ +#define DFU_VERSION 0x0110 + +/** DFU Class Subclass */ +#define DFU_SUBCLASS_DFU 0x01 + +/** DFU Class runtime Protocol */ +#define DFU_PROTOCOL_RUNTIME 0x01 + +/** DFU Class DFU mode Protocol */ +#define DFU_PROTOCOL_MODE 0x02 + +/** + * @brief DFU Class Specific Requests + */ +#define DFU_REQUEST_DETACH 0x00 +#define DFU_REQUEST_DNLOAD 0x01 +#define DFU_REQUEST_UPLOAD 0x02 +#define DFU_REQUEST_GETSTATUS 0x03 +#define DFU_REQUEST_CLRSTATUS 0x04 +#define DFU_REQUEST_GETSTATE 0x05 +#define DFU_REQUEST_ABORT 0x06 + +/** DFU FUNCTIONAL descriptor type */ +#define DFU_FUNC_DESC 0x21 + +/** DFU attributes DFU Functional Descriptor */ +#define DFU_ATTR_WILL_DETACH 0x08 +#define DFU_ATTR_MANIFESTATION_TOLERANT 0x04 +#define DFU_ATTR_CAN_UPLOAD 0x02 +#define DFU_ATTR_CAN_DNLOAD 0x01 + +/** bStatus values for the DFU_GETSTATUS response */ +#define DFU_STATUS_OK 0x00U +#define DFU_STATUS_ERR_TARGET 0x01U +#define DFU_STATUS_ERR_FILE 0x02U +#define DFU_STATUS_ERR_WRITE 0x03U +#define DFU_STATUS_ERR_ERASE 0x04U +#define DFU_STATUS_ERR_CHECK_ERASED 0x05U +#define DFU_STATUS_ERR_PROG 0x06U +#define DFU_STATUS_ERR_VERIFY 0x07U +#define DFU_STATUS_ERR_ADDRESS 0x08U +#define DFU_STATUS_ERR_NOTDONE 0x09U +#define DFU_STATUS_ERR_FIRMWARE 0x0AU +#define DFU_STATUS_ERR_VENDOR 0x0BU +#define DFU_STATUS_ERR_USB 0x0CU +#define DFU_STATUS_ERR_POR 0x0DU +#define DFU_STATUS_ERR_UNKNOWN 0x0EU +#define DFU_STATUS_ERR_STALLEDPKT 0x0FU + +/** bState values for the DFU_GETSTATUS response */ +#define DFU_STATE_APP_IDLE 0U +#define DFU_STATE_APP_DETACH 1U +#define DFU_STATE_DFU_IDLE 2U +#define DFU_STATE_DFU_DNLOAD_SYNC 3U +#define DFU_STATE_DFU_DNLOAD_BUSY 4U +#define DFU_STATE_DFU_DNLOAD_IDLE 5U +#define DFU_STATE_DFU_MANIFEST_SYNC 6U +#define DFU_STATE_DFU_MANIFEST 7U +#define DFU_STATE_DFU_MANIFEST_WAIT_RESET 8U +#define DFU_STATE_DFU_UPLOAD_IDLE 9U +#define DFU_STATE_DFU_ERROR 10U + +/** Run-Time Functional Descriptor */ +struct dfu_runtime_descriptor { + uint8_t bLength; /**<\brief Descriptor length in bytes.*/ + uint8_t bDescriptorType; /**<\brief DFU functional descriptor type.*/ + uint8_t bmAttributes; /**<\brief USB DFU capabilities \ref USB_DFU_CAPAB*/ + uint16_t wDetachTimeout; /**<\brief USB DFU detach timeout in ms.*/ + uint16_t wTransferSize; /**<\brief USB DFU maximum transfer block size in bytes.*/ + uint16_t bcdDFUVersion; /**<\brief USB DFU version \ref VERSION_BCD utility macro.*/ +} __PACKED; + +/**\brief Payload packet to response in DFU_GETSTATUS request */ +struct dfu_info { + uint8_t bStatus; /**<\brief An indication of the status resulting from the + * execution of the most recent request.*/ + uint8_t bPollTimeout; /**<\brief Minimum time (LSB) in ms, that the host should wait + * before sending a subsequent DFU_GETSTATUS request.*/ + uint16_t wPollTimeout; /**<\brief Minimum time (MSB) in ms, that the host should wait + * before sending a subsequent DFU_GETSTATUS request.*/ + uint8_t bState; /**<\brief An indication of the state that the device is going + * to enter immediately following transmission of this response.*/ + uint8_t iString; /**<\brief Index of the status string descriptor.*/ +}; + +#endif /* _USB_DFU_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usbd_dfu.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usbd_dfu.c new file mode 100644 index 00000000..88901ffe --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usbd_dfu.c @@ -0,0 +1,87 @@ +/** + * @file usbd_dfu.c + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbd_core.h" +#include "usbd_dfu.h" + +/* Device data structure */ +struct dfu_cfg_priv { + struct dfu_info info; +} usbd_dfu_cfg; + +static int dfu_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USB_LOG_WRN("DFU Class request: " + "bRequest 0x%02x\r\n", + setup->bRequest); + + switch (setup->bRequest) { + case DFU_REQUEST_DETACH: + break; + case DFU_REQUEST_DNLOAD: + break; + case DFU_REQUEST_UPLOAD: + break; + case DFU_REQUEST_GETSTATUS: + break; + case DFU_REQUEST_CLRSTATUS: + break; + case DFU_REQUEST_GETSTATE: + break; + case DFU_REQUEST_ABORT: + break; + default: + USB_LOG_WRN("Unhandled DFU Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + + return 0; +} + +static void dfu_notify_handler(uint8_t event, void *arg) +{ + switch (event) { + case USBD_EVENT_RESET: + + break; + + default: + break; + } +} + +void usbd_dfu_add_interface(usbd_class_t *devclass, usbd_interface_t *intf) +{ + static usbd_class_t *last_class = NULL; + + if (last_class != devclass) { + last_class = devclass; + usbd_class_register(devclass); + } + + intf->class_handler = dfu_class_request_handler; + intf->custom_handler = NULL; + intf->vendor_handler = NULL; + intf->notify_handler = dfu_notify_handler; + + usbd_class_add_interface(devclass, intf); +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usbd_dfu.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usbd_dfu.h new file mode 100644 index 00000000..75905823 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/dfu/usbd_dfu.h @@ -0,0 +1,38 @@ +/** + * @file usbd_dfu.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBD_DFU_H_ +#define _USBD_DFU_H_ + +#include "usb_dfu.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void usbd_dfu_add_interface(usbd_class_t *devclass, usbd_interface_t *intf); + +#ifdef __cplusplus +} +#endif + +#endif /* _USBD_DFU_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usb_hid.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usb_hid.h new file mode 100644 index 00000000..113b3e16 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usb_hid.h @@ -0,0 +1,708 @@ +/** + * @file + * @brief Human Interface Device (HID) Class public header + * + * Header follows Device Class Definition for Human Interface Devices (HID) + * Version 1.11 document (HID1_11-1.pdf). + */ +#ifndef __HID_H_ +#define __HID_H_ + +/* Subclass codes (HID 4.2) */ +#define HID_SUBCLASS_NONE 0 /* No subclass */ +#define HID_SUBCLASS_BOOTIF 1 /* Boot Interface Subclass */ + +/* HID Protocol Codes (HID 4.3) */ +#define HID_PROTOCOL_NONE 0x00 +#define HID_PROTOCOL_BOOT 0x00 +#define HID_PROTOCOL_KEYBOARD 0x01 +#define HID_PROTOCOL_REPORT 0x01 +#define HID_PROTOCOL_MOUSE 0x02 + +/* HID Class Descriptor Types (HID 7.1) */ +#define HID_DESCRIPTOR_TYPE_HID 0x21 +#define HID_DESCRIPTOR_TYPE_HID_REPORT 0x22 +#define HID_DESCRIPTOR_TYPE_HID_PHYSICAL 0x23 + +/* HID Class Specific Requests (HID 7.2) */ +#define HID_REQUEST_GET_REPORT 0x01 +#define HID_REQUEST_GET_IDLE 0x02 +#define HID_REQUEST_GET_PROTOCOL 0x03 +#define HID_REQUEST_SET_REPORT 0x09 +#define HID_REQUEST_SET_IDLE 0x0A +#define HID_REQUEST_SET_PROTOCOL 0x0B + +/* Report Type (MS byte of wValue for GET_REPORT) (HID 7.2.1) */ +#define HID_REPORT_INPUT 0x01 +#define HID_REPORT_OUTPUT 0x02 +#define HID_REPORT_FEATURE 0x03 + +/* HID Descriptor ***********************************************************/ + +#define HID_COUNTRY_NONE 0x00 /* Not Supported */ +#define HID_COUNTRY_ARABIC 0x01 /* Arabic */ +#define HID_COUNTRY_BELGIAN 0x02 /* Belgian */ +#define HID_COUNTRY_CANADA 0x03 /* Canadian-Bilingual */ +#define HID_COUNTRY_CANADRFR 0x04 /* Canadian-French */ +#define HID_COUNTRY_CZECH 0x05 /* Czech Republic */ +#define HID_COUNTRY_DANISH 0x06 /* Danish */ +#define HID_COUNTRY_FINNISH 0x07 /* Finnish */ +#define HID_COUNTRY_FRENCH 0x08 /* French */ +#define HID_COUNTRY_GERMAN 0x09 /* German */ +#define HID_COUNTRY_GREEK 0x10 /* Greek */ +#define HID_COUNTRY_HEBREW 0x11 /* Hebrew */ +#define HID_COUNTRY_HUNGARY 0x12 /* Hungary */ +#define HID_COUNTRY_ISO 0x13 /* International (ISO) */ +#define HID_COUNTRY_ITALIAN 0x14 /* Italian */ +#define HID_COUNTRY_JAPAN 0x15 /* Japan (Katakana) */ +#define HID_COUNTRY_KOREAN 0x16 /* Korean */ +#define HID_COUNTRY_LATINAM 0x17 /* Latin American */ +#define HID_COUNTRY_DUTCH 0x18 /* Netherlands/Dutch */ +#define HID_COUNTRY_NORWEGIAN 0x19 /* Norwegian */ +#define HID_COUNTRY_PERSIAN 0x20 /* Persian (Farsi) */ +#define HID_COUNTRY_POLAND 0x21 /* Poland */ +#define HID_COUNTRY_PORTUGUESE 0x22 /* Portuguese */ +#define HID_COUNTRY_RUSSIA 0x23 /* Russia */ +#define HID_COUNTRY_SLOVAKIA 0x24 /* Slovakia */ +#define HID_COUNTRY_SPANISH 0x25 /* Spanish */ +#define HID_COUNTRY_SWEDISH 0x26 /* Swedish */ +#define HID_COUNTRY_SWISSFR 0x27 /* Swiss/French */ +#define HID_COUNTRY_SWISSGR 0x28 /* Swiss/German */ +#define HID_COUNTRY_SWITZERLAND 0x29 /* Switzerland */ +#define HID_COUNTRY_TAIWAN 0x30 /* Taiwan */ +#define HID_COUNTRY_TURKISHQ 0x31 /* Turkish-Q */ +#define HID_COUNTRY_UK 0x32 /* UK */ +#define HID_COUNTRY_US 0x33 /* US */ +#define HID_COUNTRY_YUGOSLAVIA 0x34 /* Yugoslavia */ +#define HID_COUNTRY_TURKISHF 0x35 /* Turkish-F */ + +/* HID report items */ +#define HID_REPORT_ITEM_SIZE_MASK 0x03 +#define HID_REPORT_ITEM_SIZE_0 0x00 /* No data follows */ +#define HID_REPORT_ITEM_SIZE_1 0x01 /* 1 byte of data follows */ +#define HID_REPORT_ITEM_SIZE_2 0x02 /* 2 bytes of data follow */ +#define HID_REPORT_ITEM_SIZE_4 0x03 /* 4 bytes of data follow */ +#define HID_REPORT_ITEM_TYPE_MASK 0x0c +#define HID_REPORT_ITEM_TYPE_MAIN 0x00 +#define HID_REPORT_ITEM_TYPE_GLOBAL 0x04 +#define HID_REPORT_ITEM_TYPE_LOCAL 0x08 +#define HID_REPORT_ITEM_TAG_MASK 0xf0 + +/* Main Items (HID 6.2.2.4) */ +#define HID_MAIN_ITEM_CONSTANT (1 << 0) /* Constant(1) vs Data(0) */ +#define HID_MAIN_ITEM_VARIABLE (1 << 1) /* Variable(1) vs Array(0) */ +#define HID_MAIN_ITEM_RELATIVE (1 << 2) /* Relative(1) vs Absolute(0) */ +#define HID_MAIN_ITEM_WRAP (1 << 3) /* Wrap(1) vs No Wrap(0) */ +#define HID_MAIN_ITEM_NONLINEAR (1 << 4) /* Non Linear(1) vs Linear(0) */ +#define HID_MAIN_ITEM_NOPREFERRED (1 << 5) /* No Preferred (1) vs Preferred State(0) */ +#define HID_MAIN_ITEM_NULLSTATE (1 << 6) /* Null state(1) vs No Null position(0) */ +#define HID_MAIN_ITEM_VOLATILE (1 << 7) /* Volatile(1) vs Non volatile(0) */ +#define HID_MAIN_ITEM_BUFFEREDBYTES (1 << 8) /* Buffered Bytes(1) vs Bit Field(0) */ + +#define HID_MAIN_ITEM_SIZE(pfx) ((pfx)&HID_REPORT_ITEM_SIZE_MASK) +#define HID_MAIN_ITEM_INPUT_PREFIX 0x80 +#define HID_MAIN_ITEM_INPUT_CONSTANT HID_MAIN_ITEM_CONSTANT +#define HID_MAIN_ITEM_INPUT_VARIABLE HID_MAIN_ITEM_VARIABLE +#define HID_MAIN_ITEM_INPUT_RELATIVE HID_MAIN_ITEM_RELATIVE +#define HID_MAIN_ITEM_INPUT_WRAP HID_MAIN_ITEM_WRAP +#define HID_MAIN_ITEM_INPUT_NONLINEAR HID_MAIN_ITEM_NONLINEAR +#define HID_MAIN_ITEM_INPUT_NOPREFERRED HID_MAIN_ITEM_NOPREFERRED +#define HID_MAIN_ITEM_INPUT_NULLSTATE HID_MAIN_ITEM_NULLSTATE +#define HID_MAIN_ITEM_INPUT_BUFFEREDBYTES HID_MAIN_ITEM_BUFFEREDBYTES + +#define HID_MAIN_ITEM_OUTPUT_PREFIX 0x90 +#define HID_MAIN_ITEM_OUTPUT_CONSTANT HID_MAIN_ITEM_CONSTANT +#define HID_MAIN_ITEM_OUTPUT_VARIABLE HID_MAIN_ITEM_VARIABLE +#define HID_MAIN_ITEM_OUTPUT_RELATIVE HID_MAIN_ITEM_RELATIVE +#define HID_MAIN_ITEM_OUTPUT_WRAP HID_MAIN_ITEM_WRAP +#define HID_MAIN_ITEM_OUTPUT_NONLINEAR HID_MAIN_ITEM_NONLINEAR +#define HID_MAIN_ITEM_OUTPUT_NOPREFERRED HID_MAIN_ITEM_NOPREFERRED +#define HID_MAIN_ITEM_OUTPUT_NULLSTATE HID_MAIN_ITEM_NULLSTATE +#define HID_MAIN_ITEM_OUTPUT_VOLATILE HID_MAIN_ITEM_VOLATILE +#define HID_MAIN_ITEM_OUTPUT_BUFFEREDBYTES HID_MAIN_ITEM_BUFFEREDBYTES + +#define HID_MAIN_ITEM_FEATURE_PREFIX 0xb0 +#define HID_MAIN_ITEM_FEATURE_CONSTANT HID_MAIN_ITEM_CONSTANT +#define HID_MAIN_ITEM_FEATURE_VARIABLE HID_MAIN_ITEM_VARIABLE +#define HID_MAIN_ITEM_FEATURE_RELATIVE HID_MAIN_ITEM_RELATIVE +#define HID_MAIN_ITEM_FEATURE_WRAP HID_MAIN_ITEM_WRAP +#define HID_MAIN_ITEM_FEATURE_NONLINEAR HID_MAIN_ITEM_NONLINEAR +#define HID_MAIN_ITEM_FEATURE_NOPREFERRED HID_MAIN_ITEM_NOPREFERRED +#define HID_MAIN_ITEM_FEATURE_NULLSTATE HID_MAIN_ITEM_NULLSTATE +#define HID_MAIN_ITEM_FEATURE_VOLATILE HID_MAIN_ITEM_VOLATILE +#define HID_MAIN_ITEM_FEATURE_BUFFEREDBYTES HID_MAIN_ITEM_BUFFEREDBYTES + +#define HID_MAIN_ITEM_COLLECTION_PREFIX 0xa0 +#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0x00 /* Physical (group of axes) */ +#define HID_MAIN_ITEM_COLLECTION_APPL 0x01 /* Application (mouse, keyboard) */ +#define HID_MAIN_ITEM_COLLECTION_LOGICAL 0x02 /* Logical (interrelated data) */ +#define HID_MAIN_ITEM_COLLECTION_REPORT 0x03 /* Report */ +#define HID_MAIN_ITEM_COLLECTION_ARRAY 0x04 /* Named Array */ +#define HID_MAIN_ITEM_COLLECTION_SWITCH 0x05 /* Usage Switch */ +#define HID_MAIN_ITEM_COLLECTION_MODIFIER 0x06 /* Usage Modifier */ +#define HID_MAIN_ITEM_ENDCOLLECTION_PREFIX 0xc0 + +/* Global Items (HID 6.2.2.7) */ +#define HID_GLOBAL_ITEM_SIZE(pfx) ((pfx)&HID_REPORT_ITEM_SIZE_MASK) +#define HID_GLOBAL_ITEM_USAGEPAGE_PREFIX 0x04 /* Usage Page */ +#define HID_GLOBAL_ITEM_LOGICALMIN_PREFIX 0x14 /* Logical Minimum */ +#define HID_GLOBAL_ITEM_LOGICALMAX_PREFIX 0x24 /* Logical Maximum */ +#define HID_GLOBAL_ITEM_PHYSICALMIN_PREFIX 0x34 /* Physical Minimum */ +#define HID_GLOBAL_ITEM_PHYSMICALAX_PREFIX 0x44 /* Physical Maximum */ +#define HID_GLOBAL_ITEM_UNITEXP_PREFIX 0x54 /* Unit Exponent */ +#define HID_GLOBAL_ITEM_UNIT_PREFIX 0x64 /* Unit */ +#define HID_GLOBAL_ITEM_REPORTSIZE_PREFIX 0x74 /* Report Size */ +#define HID_GLOBAL_ITEM_REPORTID_PREFIX 0x84 /* Report ID */ +#define HID_GLOBAL_ITEM_REPORTCOUNT_PREFIX 0x94 /* Report Count */ +#define HID_GLOBAL_ITEM_PUSH_PREFIX 0xa4 /* Push */ +#define HID_GLOBAL_ITEM_POP_PREFIX 0xb4 /* Pop */ + +/* Local Items (HID 6.2.2.8) */ +#define HID_LOCAL_ITEM_SIZE(pfx) ((pfx)&HID_REPORT_ITEM_SIZE_MASK) +#define HID_LOCAL_ITEM_USAGE_PREFIX 0x08 /* Usage */ +#define HID_LOCAL_ITEM_USAGEMIN_PREFIX 0x18 /* Usage Minimum */ +#define HID_LOCAL_ITEM_USAGEMAX_PREFIX 0x28 /* Usage Maximum */ +#define HID_LOCAL_ITEM_DESIGNATORIDX_PREFIX 0x38 /* Designator Index */ +#define HID_LOCAL_ITEM_DESIGNATORMIN_PREFIX 0x48 /* Designator Minimum */ +#define HID_LOCAL_ITEM_DESIGNATORMAX_PREFIX 0x58 /* Designator Maximum */ +#define HID_LOCAL_ITEM_STRINGIDX_PREFIX 0x78 /* String Index */ +#define HID_LOCAL_ITEM_STRINGMIN_PREFIX 0x88 /* String Minimum */ +#define HID_LOCAL_ITEM_STRINGMAX_PREFIX 0x98 /* xx */ +#define HID_LOCAL_ITEM_DELIMITER_PREFIX 0xa8 /* Delimiter */ + +/* Modifier Keys (HID 8.3) */ +#define HID_MODIFER_LCTRL (1 << 0) /* Left Ctrl */ +#define HID_MODIFER_LSHIFT (1 << 1) /* Left Shift */ +#define HID_MODIFER_LALT (1 << 2) /* Left Alt */ +#define HID_MODIFER_LGUI (1 << 3) /* Left GUI */ +#define HID_MODIFER_RCTRL (1 << 4) /* Right Ctrl */ +#define HID_MODIFER_RSHIFT (1 << 5) /* Right Shift */ +#define HID_MODIFER_RALT (1 << 6) /* Right Alt */ +#define HID_MODIFER_RGUI (1 << 7) /* Right GUI */ + +/* Keyboard output report (1 byte) (HID B.1) */ +#define HID_KBD_OUTPUT_REPORT_NUMLOCK (1 << 0) +#define HID_KBD_OUTPUT_REPORT_CAPSLOCK (1 << 1) +#define HID_KBD_OUTPUT_REPORT_SCROLLLOCK (1 << 2) +#define HID_KBD_OUTPUT_REPORT_COMPOSE (1 << 3) +#define HID_KBD_OUTPUT_REPORT_KANA (1 << 4) + +/* Mouse input report (HID B.2) */ +#define HID_MOUSE_INPUT_REPORT_BUTTON1 (1 << 0) +#define HID_MOUSE_INPUT_REPORT_BUTTON2 (1 << 1) +#define HID_MOUSE_INPUT_REPORT_BUTTON3 (1 << 2) +#define HID_MOUSE_INPUT_REPORT_BUTTON_MASK (7) + +/* Joystick input report (4 bytes) (HID D.1) */ +#define HID_JS_INPUT_REPORT_HATSWITCH_SHIFT (0) +#define HID_JS_INPUT_REPORT_HATSWITCH_MASK (15 << HID_JSIN_HATSWITCH_SHIFT) +#define HID_JS_INPUT_REPORT_BUTTON1 (1 << 4) +#define HID_JS_INPUT_REPORT_BUTTON2 (1 << 5) +#define HID_JS_INPUT_REPORT_BUTTON3 (1 << 6) +#define HID_JS_INPUT_REPORT_BUTTON4 (1 << 7) + +/* Usage pages (HuT 3) */ +#define HID_USAGE_PAGE_UNDEFINED 0x00 /* Undefined */ +#define HID_USAGE_PAGE_GENERIC_DCTRL 0x01 /* Generic Desktop Controls */ +#define HID_USAGE_PAGE_SIMCTRL 0x02 /* Simulation Controls */ +#define HID_USAGE_PAGE_VRCTRL 0x03 /* VR Controls */ +#define HID_USAGE_PAGE_SPORTCTRL 0x04 /* Sport Controls */ +#define HID_USAGE_PAGE_GAMECTRL 0x05 /* Game Controls */ +#define HID_USAGE_PAGE_GENERIC_DEVCTRL 0x06 /* Generic Device Controls */ +#define HID_USAGE_PAGE_KBD 0x07 /* Keyboard/Keypad */ +#define HID_USAGE_PAGE_LEDS 0x08 /* LEDs */ +#define HID_USAGE_PAGE_BUTTON 0x09 /* Button */ +#define HID_USAGE_PAGE_ORDINAL 0x0a /* Ordinal */ +#define HID_USAGE_PAGE_TELEPHONY 0x0b /* Telephony */ +#define HID_USAGE_PAGE_CONSUMER 0x0c /* Consumer */ +#define HID_USAGE_PAGE_DIGITIZER 0x0d /* Digitizer */ + /* 0x0e Reserved */ +#define HID_USAGE_PAGE_PIDPAGE 0x0f /* PID Page Physical Interface Device */ +#define HID_USAGE_PAGE_UNICODE 0x10 /* Unicode */ + /* 0x11-13 Reserved */ +#define HID_USAGE_PAGE_ALPHA_DISPLAY 0x14 /* Alphanumeric Display */ + /* 0x15-3f Reserved */ +#define HID_USAGE_PAGE_MEDICAL 0x40 /* Medical Instruments */ + /* 0x41-7f Reserved */ + /* 0x80-83 Monitor Devices */ + /* 0x84-87 Power Devices */ + /* 0x88-8b Reserved */ +#define HID_USAGE_PAGE_BARCODE_SCANNER 0x8c /* Bar Code Scanner page */ +#define HID_USAGE_PAGE_SCALE 0x8d /* Scale page */ +#define HID_USAGE_PAGE_MSR 0x8e /* Magnetic Stripe Reading (MSR) Devices */ +#define HID_USAGE_PAGE_POS 0x8f /* Point of Sale devices */ +#define HID_USAGE_PAGE_CAMERA_CTRL 0x90 /* Camera Control Page */ + +/* Generic Desktop Page Usage IDs (HuT 4) */ +#define HID_DESKTOP_USAGE_UNDEFINED 0x00 /* Undefined */ +#define HID_DESKTOP_USAGE_POINTER 0x01 /* Pointer */ +#define HID_DESKTOP_USAGE_MOUSE 0x02 /* Mouse */ + /* 0x03 Reserved */ +#define HID_DESKTOP_USAGE_JOYSTICK 0x04 /* Joystick */ +#define HID_DESKTOP_USAGE_GAMEPAD 0x05 /* Game Pad */ +#define HID_DESKTOP_USAGE_KEYBOARD 0x06 /* Keyboard */ +#define HID_DESKTOP_USAGE_KEYPAD 0x07 /* Keypad */ +#define HID_DESKTOP_USAGE_MULTIAXIS 0x08 /* Multi-axis Controller */ +#define HID_DESKTOP_USAGE_TABLET 0x09 /* Tablet PC System Controls */ + /* 0x0a-2f Reserved */ +#define HID_DESKTOP_USAGE_X 0x30 /* X */ +#define HID_DESKTOP_USAGE_Y 0x31 /* Y */ +#define HID_DESKTOP_USAGE_Z 0x32 /* Z */ +#define HID_DESKTOP_USAGE_RX 0x33 /* Rx */ +#define HID_DESKTOP_USAGE_RY 0x34 /* Ry */ +#define HID_DESKTOP_USAGE_RZ 0x35 /* Rz */ +#define HID_DESKTOP_USAGE_SLIDER 0x36 /* Slider */ +#define HID_DESKTOP_USAGE_DIAL 0x37 /* Dial */ +#define HID_DESKTOP_USAGE_WHEEL 0x38 /* Wheel */ +#define HID_DESKTOP_USAGE_HATSWITCH 0x39 /* Hat switch */ +#define HID_DESKTOP_USAGE_COUNTED 0x3a /* Counted Buffer */ +#define HID_DESKTOP_USAGE_BYTECOUNT 0x3b /* Byte Count */ +#define HID_DESKTOP_USAGE_MOTION 0x3c /* Motion Wakeup */ +#define HID_DESKTOP_USAGE_START 0x3d /* Start */ +#define HID_DESKTOP_USAGE_SELECT 0x3e /* Select */ + /* 0x3f Reserved */ +#define HID_DESKTOP_USAGE_VX 0x40 /* Vx */ +#define HID_DESKTOP_USAGE_VY 0x41 /* Vy */ +#define HID_DESKTOP_USAGE_VZ 0x42 /* Vz */ +#define HID_DESKTOP_USAGE_VBRX 0x43 /* Vbrx */ +#define HID_DESKTOP_USAGE_VBRY 0x44 /* Vbry */ +#define HID_DESKTOP_USAGE_VBRZ 0x45 /* Vbrz */ +#define HID_DESKTOP_USAGE_VNO 0x46 /* Vno */ +#define HID_DESKTOP_USAGE_FEATURE 0x47 /* Feature Notification */ +#define HID_DESKTOP_USAGE_RESOLUTION 0x48 /* Resolution Multiplier */ + /* 0x49-7f Reserved */ +#define HID_DESKTOP_USAGE_CONTROL 0x80 /* System Control */ +#define HID_DESKTOP_USAGE_POWERDOWN 0x81 /* System Power Down */ +#define HID_DESKTOP_USAGE_SLEEP 0x82 /* System Sleep */ +#define HID_DESKTOP_USAGE_WAKEUP 0x83 /* System Wake Up */ +#define HID_DESKTOP_USAGE_CONTEXT_MENU 0x84 /* System Context Menu */ +#define HID_DESKTOP_USAGE_MAIN_MENU 0x85 /* System Main Menu */ +#define HID_DESKTOP_USAGE_APP_MENU 0x86 /* System App Menu */ +#define HID_DESKTOP_USAGE_MENU_HELP 0x87 /* System Menu Help */ +#define HID_DESKTOP_USAGE_MENU_EXIT 0x88 /* System Menu Exit */ +#define HID_DESKTOP_USAGE_MENU_SELECT 0x89 /* System Menu Select */ +#define HID_DESKTOP_USAGE_MENU_RIGHT 0x8a /* System Menu Right */ +#define HID_DESKTOP_USAGE_MENU_LEFT 0x8b /* System Menu Left */ +#define HID_DESKTOP_USAGE_MENU_UP 0x8c /* System Menu Up */ +#define HID_DESKTOP_USAGE_MENU_DOWN 0x8d /* System Menu Down */ +#define HID_DESKTOP_USAGE_COLD_RESTART 0x8e /* System Cold Restart */ +#define HID_DESKTOP_USAGE_WARM_RESTART 0x8f /* System Warm Restart */ +#define HID_DESKTOP_USAGE_DPAD_UP 0x90 /* D-pad Up */ +#define HID_DESKTOP_USAGE_DPAD_DOWN 0x91 /* D-pad Down */ +#define HID_DESKTOP_USAGE_DPAD_RIGHT 0x92 /* D-pad Right */ +#define HID_DESKTOP_USAGE_DPAD_LEFT 0x93 /* D-pad Left */ + /* 0x94-9f Reserved */ +#define HID_DESKTOP_USAGE_DOCK 0xa0 /* System Dock */ +#define HID_DESKTOP_USAGE_UNDOCK 0xa1 /* System Undock */ +#define HID_DESKTOP_USAGE_SETUP 0xa2 /* System Setup */ +#define HID_DESKTOP_USAGE_BREAK 0xa3 /* System Break */ +#define HID_DESKTOP_USAGE_DEBUG_BREAK 0xa4 /* System Debugger Break */ +#define HID_DESKTOP_USAGE_APP_BREAK 0xa5 /* Application Break */ +#define HID_DESKTOP_USAGE_APP_DEBUG_BREAK 0xa6 /* Application Debugger Break */ +#define HID_DESKTOP_USAGE_MUTE 0xa7 /* System Speaker Mute */ +#define HID_DESKTOP_USAGE_HIBERNATE 0xa8 /* System Hibernate */ + /* 0xa9-af Reserved */ +#define HID_DESKTOP_USAGE_DISPLAY_INVERT 0xb0 /* System Display Invert */ +#define HID_DESKTOP_USAGE_DISPALY_INTERNAL 0xb1 /* System Display Internal */ +#define HID_DESKTOP_USAGE_DISPLAY_EXTERNAL 0xb2 /* System Display External */ +#define HID_DESKTOP_USAGE_DISPLAY_BOTH 0xb3 /* System Display Both */ +#define HID_DESKTOP_USAGE_DISPLAY_DUAL 0xb4 /* System Display Dual */ +#define HID_DESKTOP_USAGE_DISPLAY_TOGGLE 0xb5 /* System Display Toggle Int/Ext */ +#define HID_DESKTOP_USAGE_DISPLAY_SWAP 0xb6 /* System Display Swap */ +#define HID_DESKTOP_USAGE_ 0xb7 /* System Display LCD Autoscale */ + /* 0xb8-ffff Reserved */ + +/* Keyboard usage IDs (HuT 10) */ +#define HID_KBD_USAGE_NONE 0x00 /* Reserved (no event indicated) */ +#define HID_KBD_USAGE_ERRORROLLOVER 0x01 /* Keyboard ErrorRollOver */ +#define HID_KBD_USAGE_POSTFAIL 0x02 /* Keyboard POSTFail */ +#define HID_KBD_USAGE_ERRUNDEF 0x03 /* Keyboard ErrorUndefined */ +#define HID_KBD_USAGE_A 0x04 /* Keyboard a or A (B-Z follow) */ +#define HID_KBD_USAGE_1 0x1e /* Keyboard 1 (2-9 follow) */ +#define HID_KBD_USAGE_EXCLAM 0x1e /* Keyboard 1 and ! */ +#define HID_KBD_USAGE_AT 0x1f /* Keyboard 2 and @ */ +#define HID_KBD_USAGE_POUND 0x20 /* Keyboard 3 and # */ +#define HID_KBD_USAGE_DOLLAR 0x21 /* Keyboard 4 and $ */ +#define HID_KBD_USAGE_PERCENT 0x22 /* Keyboard 5 and % */ +#define HID_KBD_USAGE_CARAT 0x23 /* Keyboard 6 and ^ */ +#define HID_KBD_USAGE_AMPERSAND 0x24 /* Keyboard 7 and & */ +#define HID_KBD_USAGE_ASTERISK 0x25 /* Keyboard 8 and * */ +#define HID_KBD_USAGE_LPAREN 0x26 /* Keyboard 9 and ( */ +#define HID_KBD_USAGE_0 0x27 /* Keyboard 0 and ) */ +#define HID_KBD_USAGE_RPAREN 0x27 /* Keyboard 0 and ) */ +#define HID_KBD_USAGE_ENTER 0x28 /* Keyboard Return (ENTER) */ +#define HID_KBD_USAGE_ESCAPE 0x29 /* Keyboard ESCAPE */ +#define HID_KBD_USAGE_DELETE 0x2a /* Keyboard DELETE (Backspace) */ +#define HID_KBD_USAGE_TAB 0x2b /* Keyboard Tab */ +#define HID_KBD_USAGE_SPACE 0x2c /* Keyboard Spacebar */ +#define HID_KBD_USAGE_HYPHEN 0x2d /* Keyboard - and (underscore) */ +#define HID_KBD_USAGE_UNDERSCORE 0x2d /* Keyboard - and (underscore) */ +#define HID_KBD_USAGE_EQUAL 0x2e /* Keyboard = and + */ +#define HID_KBD_USAGE_PLUS 0x2e /* Keyboard = and + */ +#define HID_KBD_USAGE_LBRACKET 0x2f /* Keyboard [ and { */ +#define HID_KBD_USAGE_LBRACE 0x2f /* Keyboard [ and { */ +#define HID_KBD_USAGE_RBRACKET 0x30 /* Keyboard ] and } */ +#define HID_KBD_USAGE_RBRACE 0x30 /* Keyboard ] and } */ +#define HID_KBD_USAGE_BSLASH 0x31 /* Keyboard \ and | */ +#define HID_KBD_USAGE_VERTBAR 0x31 /* Keyboard \ and | */ +#define HID_KBD_USAGE_NONUSPOUND 0x32 /* Keyboard Non-US # and ~ */ +#define HID_KBD_USAGE_TILDE 0x32 /* Keyboard Non-US # and ~ */ +#define HID_KBD_USAGE_SEMICOLON 0x33 /* Keyboard ; and : */ +#define HID_KBD_USAGE_COLON 0x33 /* Keyboard ; and : */ +#define HID_KBD_USAGE_SQUOTE 0x34 /* Keyboard ' and " */ +#define HID_KBD_USAGE_DQUOUTE 0x34 /* Keyboard ' and " */ +#define HID_KBD_USAGE_GACCENT 0x35 /* Keyboard Grave Accent and Tilde */ +#define HID_KBD_USAGE_GTILDE 0x35 /* Keyboard Grave Accent and Tilde */ +#define HID_KBD_USAGE_COMMON 0x36 /* Keyboard , and < */ +#define HID_KBD_USAGE_LT 0x36 /* Keyboard , and < */ +#define HID_KBD_USAGE_PERIOD 0x37 /* Keyboard . and > */ +#define HID_KBD_USAGE_GT 0x37 /* Keyboard . and > */ +#define HID_KBD_USAGE_DIV 0x38 /* Keyboard / and ? */ +#define HID_KBD_USAGE_QUESTION 0x38 /* Keyboard / and ? */ +#define HID_KBD_USAGE_CAPSLOCK 0x39 /* Keyboard Caps Lock */ +#define HID_KBD_USAGE_F1 0x3a /* Keyboard F1 */ +#define HID_KBD_USAGE_F2 0x3b /* Keyboard F2 */ +#define HID_KBD_USAGE_F3 0x3c /* Keyboard F3 */ +#define HID_KBD_USAGE_F4 0x3d /* Keyboard F4 */ +#define HID_KBD_USAGE_F5 0x3e /* Keyboard F5 */ +#define HID_KBD_USAGE_F6 0x3f /* Keyboard F6 */ +#define HID_KBD_USAGE_F7 0x40 /* Keyboard F7 */ +#define HID_KBD_USAGE_F8 0x41 /* Keyboard F8 */ +#define HID_KBD_USAGE_F9 0x42 /* Keyboard F9 */ +#define HID_KBD_USAGE_F10 0x43 /* Keyboard F10 */ +#define HID_KBD_USAGE_F11 0x44 /* Keyboard F11 */ +#define HID_KBD_USAGE_F12 0x45 /* Keyboard F12 */ +#define HID_KBD_USAGE_PRINTSCN 0x46 /* Keyboard PrintScreen */ +#define HID_KBD_USAGE_SCROLLLOCK 0x47 /* Keyboard Scroll Lock */ +#define HID_KBD_USAGE_PAUSE 0x48 /* Keyboard Pause */ +#define HID_KBD_USAGE_INSERT 0x49 /* Keyboard Insert */ +#define HID_KBD_USAGE_HOME 0x4a /* Keyboard Home */ +#define HID_KBD_USAGE_PAGEUP 0x4b /* Keyboard PageUp */ +#define HID_KBD_USAGE_DELFWD 0x4c /* Keyboard Delete Forward */ +#define HID_KBD_USAGE_END 0x4d /* Keyboard End */ +#define HID_KBD_USAGE_PAGEDOWN 0x4e /* Keyboard PageDown */ +#define HID_KBD_USAGE_RIGHT 0x4f /* eyboard RightArrow */ +#define HID_KBD_USAGE_LEFT 0x50 /* Keyboard LeftArrow */ +#define HID_KBD_USAGE_DOWN 0x5a /* Keyboard DownArrow */ +#define HID_KBD_USAGE_UP 0x52 /* Keyboard UpArrow */ +#define HID_KBD_USAGE_KPDNUMLOCK 0x53 /* Keypad Num Lock and Clear */ +#define HID_KBD_USAGE_KPDNUMLOCKCLEAR 0x53 /* Keypad Num Lock and Clear */ +#define HID_KBD_USAGE_KPDDIV 0x54 /* Keypad / */ +#define HID_KBD_USAGE_KPDMUL 0x55 /* Keypad * */ +#define HID_KBD_USAGE_KPDHMINUS 0x56 /* Keypad - */ +#define HID_KBD_USAGE_KPDPLUS 0x57 /* Keypad + */ +#define HID_KBD_USAGE_KPDEMTER 0x58 /* Keypad ENTER */ +#define HID_KBD_USAGE_KPD1 0x59 /* Keypad 1 (2-9 follow) */ +#define HID_KBD_USAGE_KPDEND 0x59 /* Keypad 1 and End */ +#define HID_KBD_USAGE_KPDDOWN 0x5a /* Keypad 2 and Down Arrow */ +#define HID_KBD_USAGE_KPDPAGEDN 0x5b /* Keypad 3 and PageDn */ +#define HID_KBD_USAGE_KPDLEFT 0x5c /* Keypad 4 and Left Arrow */ +#define HID_KBD_USAGE_KPDRIGHT 0x5e /* Keypad 6 and Right Arrow */ +#define HID_KBD_USAGE_KPDHOME 0x5f /* Keypad 7 and Home */ +#define HID_KBD_USAGE_KPDUP 0x60 /* Keypad 8 and Up Arrow */ +#define HID_KBD_USAGE_KPDPAGEUP 0x61 /* Keypad 9 and PageUp */ +#define HID_KBD_USAGE_KPD0 0x62 /* Keypad 0 and Insert */ +#define HID_KBD_USAGE_KPDINSERT 0x62 /* Keypad 0 and Insert */ +#define HID_KBD_USAGE_KPDDECIMALPT 0x63 /* Keypad . and Delete */ +#define HID_KBD_USAGE_KPDDELETE 0x63 /* Keypad . and Delete */ +#define HID_KBD_USAGE_NONSLASH 0x64 /* Keyboard Non-US \ and | */ +#define HID_KBD_USAGE_NONUSVERT 0x64 /* Keyboard Non-US \ and | */ +#define HID_KBD_USAGE_APPLICATION 0x65 /* Keyboard Application */ +#define HID_KBD_USAGE_POWER 0x66 /* Keyboard Power */ +#define HID_KBD_USAGE_KPDEQUAL 0x67 /* Keypad = */ +#define HID_KBD_USAGE_F13 0x68 /* Keyboard F13 */ +#define HID_KBD_USAGE_F14 0x69 /* Keyboard F14 */ +#define HID_KBD_USAGE_F15 0x6a /* Keyboard F15 */ +#define HID_KBD_USAGE_F16 0x6b /* Keyboard F16 */ +#define HID_KBD_USAGE_F17 0x6c /* Keyboard F17 */ +#define HID_KBD_USAGE_F18 0x6d /* Keyboard F18 */ +#define HID_KBD_USAGE_F19 0x6e /* Keyboard F19 */ +#define HID_KBD_USAGE_F20 0x6f /* Keyboard F20 */ +#define HID_KBD_USAGE_F21 0x70 /* Keyboard F21 */ +#define HID_KBD_USAGE_F22 0x71 /* Keyboard F22 */ +#define HID_KBD_USAGE_F23 0x72 /* Keyboard F23 */ +#define HID_KBD_USAGE_F24 0x73 /* Keyboard F24 */ +#define HID_KBD_USAGE_EXECUTE 0x74 /* Keyboard Execute */ +#define HID_KBD_USAGE_HELP 0x75 /* Keyboard Help */ +#define HID_KBD_USAGE_MENU 0x76 /* Keyboard Menu */ +#define HID_KBD_USAGE_SELECT 0x77 /* Keyboard Select */ +#define HID_KBD_USAGE_STOP 0x78 /* Keyboard Stop */ +#define HID_KBD_USAGE_AGAIN 0x79 /* Keyboard Again */ +#define HID_KBD_USAGE_UNDO 0x7a /* Keyboard Undo */ +#define HID_KBD_USAGE_CUT 0x7b /* Keyboard Cut */ +#define HID_KBD_USAGE_COPY 0x7c /* Keyboard Copy */ +#define HID_KBD_USAGE_PASTE 0x7d /* Keyboard Paste */ +#define HID_KBD_USAGE_FIND 0x7e /* Keyboard Find */ +#define HID_KBD_USAGE_MUTE 0x7f /* Keyboard Mute */ +#define HID_KBD_USAGE_VOLUP 0x80 /* Keyboard Volume Up */ +#define HID_KBD_USAGE_VOLDOWN 0x81 /* Keyboard Volume Down */ +#define HID_KBD_USAGE_LCAPSLOCK 0x82 /* Keyboard Locking Caps Lock */ +#define HID_KBD_USAGE_LNUMLOCK 0x83 /* Keyboard Locking Num Lock */ +#define HID_KBD_USAGE_LSCROLLLOCK 0x84 /* Keyboard Locking Scroll Lock */ +#define HID_KBD_USAGE_KPDCOMMA 0x85 /* Keypad Comma */ +#define HID_KBD_USAGE_KPDEQUALSIGN 0x86 /* Keypad Equal Sign */ +#define HID_KBD_USAGE_INTERNATIONAL1 0x87 /* Keyboard International 1 */ +#define HID_KBD_USAGE_INTERNATIONAL2 0x88 /* Keyboard International 2 */ +#define HID_KBD_USAGE_INTERNATIONAL3 0x89 /* Keyboard International 3 */ +#define HID_KBD_USAGE_INTERNATIONAL4 0x8a /* Keyboard International 4 */ +#define HID_KBD_USAGE_INTERNATIONAL5 0x8b /* Keyboard International 5 */ +#define HID_KBD_USAGE_INTERNATIONAL6 0x8c /* Keyboard International 6 */ +#define HID_KBD_USAGE_INTERNATIONAL7 0x8d /* Keyboard International 7 */ +#define HID_KBD_USAGE_INTERNATIONAL8 0x8e /* Keyboard International 8 */ +#define HID_KBD_USAGE_INTERNATIONAL9 0x8f /* Keyboard International 9 */ +#define HID_KBD_USAGE_LANG1 0x90 /* Keyboard LANG1 */ +#define HID_KBD_USAGE_LANG2 0x91 /* Keyboard LANG2 */ +#define HID_KBD_USAGE_LANG3 0x92 /* Keyboard LANG3 */ +#define HID_KBD_USAGE_LANG4 0x93 /* Keyboard LANG4 */ +#define HID_KBD_USAGE_LANG5 0x94 /* Keyboard LANG5 */ +#define HID_KBD_USAGE_LANG6 0x95 /* Keyboard LANG6 */ +#define HID_KBD_USAGE_LANG7 0x96 /* Keyboard LANG7 */ +#define HID_KBD_USAGE_LANG8 0x97 /* Keyboard LANG8 */ +#define HID_KBD_USAGE_LANG9 0x98 /* Keyboard LANG9 */ +#define HID_KBD_USAGE_ALTERASE 0x99 /* Keyboard Alternate Erase */ +#define HID_KBD_USAGE_SYSREQ 0x9a /* Keyboard SysReq/Attention */ +#define HID_KBD_USAGE_CANCEL 0x9b /* Keyboard Cancel */ +#define HID_KBD_USAGE_CLEAR 0x9c /* Keyboard Clear */ +#define HID_KBD_USAGE_PRIOR 0x9d /* Keyboard Prior */ +#define HID_KBD_USAGE_RETURN 0x9e /* Keyboard Return */ +#define HID_KBD_USAGE_SEPARATOR 0x9f /* Keyboard Separator */ +#define HID_KBD_USAGE_OUT 0xa0 /* Keyboard Out */ +#define HID_KBD_USAGE_OPER 0xa1 /* Keyboard Oper */ +#define HID_KBD_USAGE_CLEARAGAIN 0xa2 /* Keyboard Clear/Again */ +#define HID_KBD_USAGE_CLRSEL 0xa3 /* Keyboard CrSel/Props */ +#define HID_KBD_USAGE_EXSEL 0xa4 /* Keyboard ExSel */ +#define HID_KBD_USAGE_KPD00 0xb0 /* Keypad 00 */ +#define HID_KBD_USAGE_KPD000 0xb1 /* Keypad 000 */ +#define HID_KBD_USAGE_THOUSEPARATOR 0xb2 /* Thousands Separator */ +#define HID_KBD_USAGE_DECSEPARATOR 0xb3 /* Decimal Separator */ +#define HID_KBD_USAGE_CURRUNIT 0xb4 /* Currency Unit */ +#define HID_KBD_USAGE_CURRSUBUNIT 0xb5 /* Currency Sub-unit */ +#define HID_KBD_USAGE_KPDLPAREN 0xb6 /* Keypad ( */ +#define HID_KBD_USAGE_KPDRPAREN 0xb7 /* Keypad ) */ +#define HID_KBD_USAGE_KPDLBRACE 0xb8 /* Keypad { */ +#define HID_KBD_USAGE_KPDRBRACE 0xb9 /* Keypad } */ +#define HID_KBD_USAGE_KPDTAB 0xba /* Keypad Tab */ +#define HID_KBD_USAGE_KPDBACKSPACE 0xbb /* Keypad Backspace */ +#define HID_KBD_USAGE_KPDA 0xbc /* Keypad A (B-F follow) */ +#define HID_KBD_USAGE_KPDXOR 0xc2 /* Keypad XOR */ +#define HID_KBD_USAGE_KPDEXP 0xc3 /* Keypad ^ */ +#define HID_KBD_USAGE_KPDPERCENT 0xc4 /* Keypad % */ +#define HID_KBD_USAGE_KPDLT 0xc5 /* Keypad < */ +#define HID_KBD_USAGE_KPDGT 0xc6 /* Keypad > */ +#define HID_KBD_USAGE_KPDAMPERSAND 0xc7 /* Keypad & */ +#define HID_KBD_USAGE_KPDAND 0xc8 /* Keypad && */ +#define HID_KBD_USAGE_KPDVERT 0xc9 /* Keypad | */ +#define HID_KBD_USAGE_KPDOR 0xca /* Keypad || */ +#define HID_KBD_USAGE_KPDCOLON 0xcb /* Keypad : */ +#define HID_KBD_USAGE_KPDPOUND 0xcc /* Keypad # */ +#define HID_KBD_USAGE_KPDSPACE 0xcd /* Keypad Space */ +#define HID_KBD_USAGE_KPDAT 0xce /* Keypad @ */ +#define HID_KBD_USAGE_KPDEXCLAM 0xcf /* Keypad ! */ +#define HID_KBD_USAGE_KPDMEMSTORE 0xd0 /* Keypad Memory Store */ +#define HID_KBD_USAGE_KPDMEMRECALL 0xd1 /* Keypad Memory Recall */ +#define HID_KBD_USAGE_KPDMEMCLEAR 0xd2 /* Keypad Memory Clear */ +#define HID_KBD_USAGE_KPDMEMADD 0xd3 /* Keypad Memory Add */ +#define HID_KBD_USAGE_KPDMEMSUB 0xd4 /* Keypad Memory Subtract */ +#define HID_KBD_USAGE_KPDMEMMULT 0xd5 /* Keypad Memory Multiply */ +#define HID_KBD_USAGE_KPDMEMDIV 0xd6 /* Keypad Memory Divide */ +#define HID_KBD_USAGE_KPDPLUSMINUS 0xd7 /* Keypad +/- */ +#define HID_KBD_USAGE_KPDCLEAR 0xd8 /* Keypad Clear */ +#define HID_KBD_USAGE_KPDCLEARENTRY 0xd9 /* Keypad Clear Entry */ +#define HID_KBD_USAGE_KPDBINARY 0xda /* Keypad Binary */ +#define HID_KBD_USAGE_KPDOCTAL 0xdb /* Keypad Octal */ +#define HID_KBD_USAGE_KPDDECIMAL 0xdc /* Keypad Decimal */ +#define HID_KBD_USAGE_KPDHEXADECIMAL 0xdd /* Keypad Hexadecimal */ +#define HID_KBD_USAGE_LCTRL 0xe0 /* Keyboard LeftControl */ +#define HID_KBD_USAGE_LSHIFT 0xe1 /* Keyboard LeftShift */ +#define HID_KBD_USAGE_LALT 0xe2 /* Keyboard LeftAlt */ +#define HID_KBD_USAGE_LGUI 0xe3 /* Keyboard Left GUI */ +#define HID_KBD_USAGE_RCTRL 0xe4 /* Keyboard RightControl */ +#define HID_KBD_USAGE_RSHIFT 0xe5 /* Keyboard RightShift */ +#define HID_KBD_USAGE_RALT 0xe6 /* Keyboard RightAlt */ +#define HID_KBD_USAGE_RGUI 0xe7 /* Keyboard Right GUI */ + +#define HID_KBD_USAGE_MAX 0xe7 + +/* HID Report Definitions */ +struct usb_hid_class_subdescriptor { + uint8_t bDescriptorType;/* Class descriptor type (See 7.1) */ + uint16_t wDescriptorLength;/* Size of the report descriptor */ +} __PACKED; + +struct usb_hid_descriptor { + uint8_t bLength; /* Size of the HID descriptor */ + uint8_t bDescriptorType;/* HID descriptor type */ + uint16_t bcdHID;/* HID class specification release */ + uint8_t bCountryCode;/* Country code */ + uint8_t bNumDescriptors;/* Number of descriptors (>=1) */ + + /* + * Specification says at least one Class Descriptor needs to + * be present (Report Descriptor). + */ + struct usb_hid_class_subdescriptor subdesc[1]; +} __PACKED; + +/* Standard Reports *********************************************************/ + +/* Keyboard input report (8 bytes) (HID B.1) */ +struct usb_hid_kbd_report +{ + uint8_t modifier; /* Modifier keys. See USBHID_MODIFIER_* definitions */ + uint8_t reserved; + uint8_t key[6]; /* Keycode 1-6 */ +}; + +/* Keyboard output report (1 byte) (HID B.1), + * see USBHID_KBDOUT_* definitions + */ + +/* Mouse input report (HID B.2) */ +struct usb_hid_mouse_report +{ + uint8_t buttons; /* See USBHID_MOUSEIN_* definitions */ + uint8_t xdisp; /* X displacement */ + uint8_t ydisp; /* y displacement */ + /* Device specific additional bytes may follow */ +#ifdef CONFIG_INPUT_MOUSE_WHEEL + uint8_t wdisp; /* Wheel displacement */ +#endif +}; + +/* Joystick input report (1 bytes) (HID D.1) */ +struct usb_hid_js_report +{ + uint8_t xpos; /* X position */ + uint8_t ypos; /* X position */ + uint8_t buttons; /* See USBHID_JSIN_* definitions */ + uint8_t throttle; /* Throttle */ +}; + +/** + * @brief HID keyboard button codes. + */ +enum hid_kbd_code { + HID_KEY_A = 4, + HID_KEY_B = 5, + HID_KEY_C = 6, + HID_KEY_D = 7, + HID_KEY_E = 8, + HID_KEY_F = 9, + HID_KEY_G = 10, + HID_KEY_H = 11, + HID_KEY_I = 12, + HID_KEY_J = 13, + HID_KEY_K = 14, + HID_KEY_L = 15, + HID_KEY_M = 16, + HID_KEY_N = 17, + HID_KEY_O = 18, + HID_KEY_P = 19, + HID_KEY_Q = 20, + HID_KEY_R = 21, + HID_KEY_S = 22, + HID_KEY_T = 23, + HID_KEY_U = 24, + HID_KEY_V = 25, + HID_KEY_W = 26, + HID_KEY_X = 27, + HID_KEY_Y = 28, + HID_KEY_Z = 29, + HID_KEY_1 = 30, + HID_KEY_2 = 31, + HID_KEY_3 = 32, + HID_KEY_4 = 33, + HID_KEY_5 = 34, + HID_KEY_6 = 35, + HID_KEY_7 = 36, + HID_KEY_8 = 37, + HID_KEY_9 = 38, + HID_KEY_0 = 39, + HID_KEY_ENTER = 40, + HID_KEY_ESC = 41, + HID_KEY_BACKSPACE = 42, + HID_KEY_TAB = 43, + HID_KEY_SPACE = 44, + HID_KEY_MINUS = 45, + HID_KEY_EQUAL = 46, + HID_KEY_LEFTBRACE = 47, + HID_KEY_RIGHTBRACE = 48, + HID_KEY_BACKSLASH = 49, + HID_KEY_HASH = 50, /* Non-US # and ~ */ + HID_KEY_SEMICOLON = 51, + HID_KEY_APOSTROPHE = 52, + HID_KEY_GRAVE = 53, + HID_KEY_COMMA = 54, + HID_KEY_DOT = 55, + HID_KEY_SLASH = 56, + HID_KEY_CAPSLOCK = 57, + HID_KEY_F1 = 58, + HID_KEY_F2 = 59, + HID_KEY_F3 = 60, + HID_KEY_F4 = 61, + HID_KEY_F5 = 62, + HID_KEY_F6 = 63, + HID_KEY_F7 = 64, + HID_KEY_F8 = 65, + HID_KEY_F9 = 66, + HID_KEY_F10 = 67, + HID_KEY_F11 = 68, + HID_KEY_F12 = 69, + HID_KEY_SYSRQ = 70, /* PRINTSCREEN */ + HID_KEY_SCROLLLOCK = 71, + HID_KEY_PAUSE = 72, + HID_KEY_INSERT = 73, + HID_KEY_HOME = 74, + HID_KEY_PAGEUP = 75, + HID_KEY_DELETE = 76, + HID_KEY_END = 77, + HID_KEY_PAGEDOWN = 78, + HID_KEY_RIGHT = 79, + HID_KEY_LEFT = 80, + HID_KEY_DOWN = 81, + HID_KEY_UP = 82, + HID_KEY_NUMLOCK = 83, + HID_KEY_KPSLASH = 84, /* NUMPAD DIVIDE */ + HID_KEY_KPASTERISK = 85, /* NUMPAD MULTIPLY */ + HID_KEY_KPMINUS = 86, + HID_KEY_KPPLUS = 87, + HID_KEY_KPENTER = 88, + HID_KEY_KP_1 = 89, + HID_KEY_KP_2 = 90, + HID_KEY_KP_3 = 91, + HID_KEY_KP_4 = 92, + HID_KEY_KP_5 = 93, + HID_KEY_KP_6 = 94, + HID_KEY_KP_7 = 95, + HID_KEY_KP_8 = 96, + HID_KEY_KP_9 = 97, + HID_KEY_KP_0 = 98, +}; + +/** + * @brief HID keyboard modifiers. + */ +enum hid_kbd_modifier { + HID_KBD_MODIFIER_NONE = 0x00, + HID_KBD_MODIFIER_LEFT_CTRL = 0x01, + HID_KBD_MODIFIER_LEFT_SHIFT = 0x02, + HID_KBD_MODIFIER_LEFT_ALT = 0x04, + HID_KBD_MODIFIER_LEFT_UI = 0x08, + HID_KBD_MODIFIER_RIGHT_CTRL = 0x10, + HID_KBD_MODIFIER_RIGHT_SHIFT = 0x20, + HID_KBD_MODIFIER_RIGHT_ALT = 0x40, + HID_KBD_MODIFIER_RIGHT_UI = 0x80, +}; + +/** + * @brief HID keyboard LEDs. + */ +enum hid_kbd_led { + HID_KBD_LED_NUM_LOCK = 0x01, + HID_KBD_LED_CAPS_LOCK = 0x02, + HID_KBD_LED_SCROLL_LOCK = 0x04, + HID_KBD_LED_COMPOSE = 0x08, + HID_KBD_LED_KANA = 0x10, +}; + +#endif /* __HID_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbd_hid.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbd_hid.c new file mode 100644 index 00000000..dfbf8d0d --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbd_hid.c @@ -0,0 +1,285 @@ +/** + * @file usbd_hid.c + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbd_core.h" +#include "usbd_hid.h" + +#define HID_STATE_IDLE 0 +#define HID_STATE_BUSY 1 + +struct usbd_hid_cfg_priv { + const uint8_t *hid_descriptor; + const uint8_t *hid_report_descriptor; + uint32_t hid_report_descriptor_len; + uint8_t current_intf_num; + uint8_t hid_state; + uint8_t report; + uint8_t idle_state; + uint8_t protocol; + + uint8_t (*get_report_callback)(uint8_t report_id, uint8_t report_type); + void (*set_report_callback)(uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len); + uint8_t (*get_idle_callback)(uint8_t report_id); + void (*set_idle_callback)(uint8_t report_id, uint8_t duration); + void (*set_protocol_callback)(uint8_t protocol); + uint8_t (*get_protocol_callback)(void); + + usb_slist_t list; +} usbd_hid_cfg[4]; + +static usb_slist_t usbd_hid_class_head = USB_SLIST_OBJECT_INIT(usbd_hid_class_head); + +static void usbd_hid_reset(void) +{ + usb_slist_t *i; + usb_slist_for_each(i, &usbd_hid_class_head) + { + struct usbd_hid_cfg_priv *hid_intf = usb_slist_entry(i, struct usbd_hid_cfg_priv, list); + hid_intf->hid_state = HID_STATE_IDLE; + hid_intf->report = 0; + hid_intf->idle_state = 0; + hid_intf->protocol = 0; + } +} + +static int hid_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USB_LOG_DBG("HID Custom request: " + "bRequest 0x%02x\r\n", + setup->bRequest); + + if (((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_IN) && + setup->bRequest == USB_REQUEST_GET_DESCRIPTOR) { + uint8_t value = (uint8_t)(setup->wValue >> 8); + uint8_t intf_num = (uint8_t)setup->wIndex; + + struct usbd_hid_cfg_priv *current_hid_intf = NULL; + usb_slist_t *i; + usb_slist_for_each(i, &usbd_hid_class_head) + { + struct usbd_hid_cfg_priv *hid_intf = usb_slist_entry(i, struct usbd_hid_cfg_priv, list); + + if (hid_intf->current_intf_num == intf_num) { + current_hid_intf = hid_intf; + break; + } + } + + if (current_hid_intf == NULL) { + return -2; + } + + switch (value) { + case HID_DESCRIPTOR_TYPE_HID: + USB_LOG_INFO("get HID Descriptor\r\n"); + *data = (uint8_t *)current_hid_intf->hid_descriptor; + *len = current_hid_intf->hid_descriptor[0]; + break; + + case HID_DESCRIPTOR_TYPE_HID_REPORT: + USB_LOG_INFO("get Report Descriptor\r\n"); + *data = (uint8_t *)current_hid_intf->hid_report_descriptor; + *len = current_hid_intf->hid_report_descriptor_len; + break; + + case HID_DESCRIPTOR_TYPE_HID_PHYSICAL: + USB_LOG_INFO("get PHYSICAL Descriptor\r\n"); + + break; + + default: + return -2; + } + + return 0; + } + + return -1; +} + +static int hid_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USB_LOG_DBG("HID Class request: " + "bRequest 0x%02x\r\n", + setup->bRequest); + + struct usbd_hid_cfg_priv *current_hid_intf = NULL; + usb_slist_t *i; + usb_slist_for_each(i, &usbd_hid_class_head) + { + struct usbd_hid_cfg_priv *hid_intf = usb_slist_entry(i, struct usbd_hid_cfg_priv, list); + uint8_t intf_num = (uint8_t)setup->wIndex; + if (hid_intf->current_intf_num == intf_num) { + current_hid_intf = hid_intf; + break; + } + } + + if (current_hid_intf == NULL) { + return -2; + } + + switch (setup->bRequest) { + case HID_REQUEST_GET_REPORT: + if (current_hid_intf->get_report_callback) + current_hid_intf->report = current_hid_intf->get_report_callback(LO_BYTE(setup->wValue), HI_BYTE(setup->wValue)); /*report id ,report type*/ + + *data = (uint8_t *)¤t_hid_intf->report; + *len = 1; + break; + case HID_REQUEST_GET_IDLE: + if (current_hid_intf->get_idle_callback) + current_hid_intf->idle_state = current_hid_intf->get_idle_callback(LO_BYTE(setup->wValue)); + + *data = (uint8_t *)¤t_hid_intf->idle_state; + *len = 1; + break; + case HID_REQUEST_GET_PROTOCOL: + if (current_hid_intf->get_protocol_callback) + current_hid_intf->protocol = current_hid_intf->get_protocol_callback(); + + *data = (uint8_t *)¤t_hid_intf->protocol; + *len = 1; + break; + case HID_REQUEST_SET_REPORT: + if (current_hid_intf->set_report_callback) + current_hid_intf->set_report_callback(LO_BYTE(setup->wValue), HI_BYTE(setup->wValue), *data, *len); /*report id ,report type,report,report len*/ + + current_hid_intf->report = **data; + break; + case HID_REQUEST_SET_IDLE: + if (current_hid_intf->set_idle_callback) + current_hid_intf->set_idle_callback(LO_BYTE(setup->wValue), HI_BYTE(setup->wIndex)); /*report id ,duration*/ + + current_hid_intf->idle_state = HI_BYTE(setup->wIndex); + break; + case HID_REQUEST_SET_PROTOCOL: + if (current_hid_intf->set_protocol_callback) + current_hid_intf->set_protocol_callback(LO_BYTE(setup->wValue)); /*protocol*/ + + current_hid_intf->protocol = LO_BYTE(setup->wValue); + break; + + default: + USB_LOG_WRN("Unhandled HID Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + + return 0; +} + +static void hid_notify_handler(uint8_t event, void *arg) +{ + switch (event) { + case USBD_EVENT_RESET: + usbd_hid_reset(); + break; + + default: + break; + } +} + +void usbd_hid_add_interface(usbd_class_t *devclass, usbd_interface_t *intf) +{ + static usbd_class_t *last_class = NULL; + static uint8_t hid_num = 0; + if (last_class != devclass) { + last_class = devclass; + usbd_class_register(devclass); + } + + intf->class_handler = hid_class_request_handler; + intf->custom_handler = hid_custom_request_handler; + intf->vendor_handler = NULL; + intf->notify_handler = hid_notify_handler; + usbd_class_add_interface(devclass, intf); + + usbd_hid_cfg[hid_num].current_intf_num = intf->intf_num; + usb_slist_add_tail(&usbd_hid_class_head, &usbd_hid_cfg[hid_num].list); + hid_num++; +} + +void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc) +{ + // usbd_hid_cfg.hid_descriptor = desc; +} + +void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len) +{ + usb_slist_t *i; + usb_slist_for_each(i, &usbd_hid_class_head) + { + struct usbd_hid_cfg_priv *hid_intf = usb_slist_entry(i, struct usbd_hid_cfg_priv, list); + + if (hid_intf->current_intf_num == intf_num) { + hid_intf->hid_report_descriptor = desc; + hid_intf->hid_report_descriptor_len = desc_len; + return; + } + } +} + +void usbd_hid_set_request_callback(uint8_t intf_num, + uint8_t (*get_report_callback)(uint8_t report_id, uint8_t report_type), + void (*set_report_callback)(uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len), + uint8_t (*get_idle_callback)(uint8_t report_id), + void (*set_idle_callback)(uint8_t report_id, uint8_t duration), + void (*set_protocol_callback)(uint8_t protocol), + uint8_t (*get_protocol_callback)(void)) +{ + usb_slist_t *i; + usb_slist_for_each(i, &usbd_hid_class_head) + { + struct usbd_hid_cfg_priv *hid_intf = usb_slist_entry(i, struct usbd_hid_cfg_priv, list); + + if (hid_intf->current_intf_num == intf_num) { + if (get_report_callback) + hid_intf->get_report_callback = get_report_callback; + if (set_report_callback) + hid_intf->set_report_callback = set_report_callback; + if (get_idle_callback) + hid_intf->get_idle_callback = get_idle_callback; + if (set_idle_callback) + hid_intf->set_idle_callback = set_idle_callback; + if (set_protocol_callback) + hid_intf->set_protocol_callback = set_protocol_callback; + if (get_protocol_callback) + hid_intf->get_protocol_callback = get_protocol_callback; + return; + } + } +} + +void usbd_hid_reset_state(void) +{ + // usbd_hid_cfg.hid_state = HID_STATE_IDLE; +} + +void usbd_hid_send_report(uint8_t ep, uint8_t *data, uint8_t len) +{ + // if(usbd_hid_cfg.hid_state == HID_STATE_IDLE) + // { + // usbd_hid_cfg.hid_state = HID_STATE_BUSY; + // usbd_ep_write(ep, data, len, NULL); + // } +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbd_hid.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbd_hid.h new file mode 100644 index 00000000..05bb8611 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbd_hid.h @@ -0,0 +1,50 @@ +/** + * @file usbd_hid.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBD_HID_H_ +#define _USBD_HID_H_ + +#include "usb_hid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void usbd_hid_descriptor_register(uint8_t intf_num, const uint8_t *desc); +void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len); +void usbd_hid_add_interface(usbd_class_t *devclass, usbd_interface_t *intf); +void usbd_hid_reset_state(void); +void usbd_hid_send_report(uint8_t ep, uint8_t *data, uint8_t len); + +void usbd_hid_set_request_callback(uint8_t intf_num, + uint8_t (*get_report_callback)(uint8_t report_id, uint8_t report_type), + void (*set_report_callback)(uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len), + uint8_t (*get_idle_callback)(uint8_t report_id), + void (*set_idle_callback)(uint8_t report_id, uint8_t duration), + void (*set_protocol_callback)(uint8_t protocol), + uint8_t (*get_protocol_callback)(void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _USBD_HID_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbh_hid.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbh_hid.c new file mode 100644 index 00000000..7fee5a9b --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbh_hid.c @@ -0,0 +1,284 @@ +/** + * @file usbh_hid.c + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbh_core.h" +#include "usbh_hid.h" + +#define DEV_FORMAT "/dev/input%d" +#define DEV_NAMELEN 16 + +static uint32_t g_devinuse = 0; + +/**************************************************************************** + * Name: usbh_hid_devno_alloc + * + * Description: + * Allocate a unique /dev/hid[n] minor number in the range 0-31. + * + ****************************************************************************/ + +static int usbh_hid_devno_alloc(struct usbh_hid *priv) +{ + uint32_t flags; + int devno; + + flags = usb_osal_enter_critical_section(); + for (devno = 0; devno < 32; devno++) { + uint32_t bitno = 1 << devno; + if ((g_devinuse & bitno) == 0) { + g_devinuse |= bitno; + priv->minor = devno; + usb_osal_leave_critical_section(flags); + return 0; + } + } + + usb_osal_leave_critical_section(flags); + return -EMFILE; +} + +/**************************************************************************** + * Name: usbh_hid_devno_free + * + * Description: + * Free a /dev/hid[n] minor number so that it can be used. + * + ****************************************************************************/ + +static void usbh_hid_devno_free(struct usbh_hid *priv) +{ + int devno = priv->minor; + + if (devno >= 0 && devno < 32) { + uint32_t flags = usb_osal_enter_critical_section(); + g_devinuse &= ~(1 << devno); + usb_osal_leave_critical_section(flags); + } +} + +/**************************************************************************** + * Name: usbh_hid_mkdevname + * + * Description: + * Format a /dev/hid[n] device name given a minor number. + * + ****************************************************************************/ + +static inline void usbh_hid_mkdevname(struct usbh_hid *priv, char *devname) +{ + snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->minor); +} + +int usbh_hid_get_report_descriptor(struct usbh_hubport *hport, uint8_t intf, uint8_t *buffer) +{ + struct usb_setup_packet *setup; + struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv; + + setup = hid_class->setup; + + if (hid_class->intf != intf) { + return -1; + } + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; + setup->wValue = HID_DESCRIPTOR_TYPE_HID_REPORT << 8; + setup->wIndex = intf; + setup->wLength = 128; + + return usbh_control_transfer(hport->ep0, setup, buffer); +} + +int usbh_hid_set_idle(struct usbh_hubport *hport, uint8_t intf, uint8_t report_id, uint8_t duration) +{ + int ret; + struct usb_setup_packet *setup; + struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv; + + setup = hid_class->setup; + + if (hid_class->intf != intf) { + return -1; + } + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = HID_REQUEST_SET_IDLE; + setup->wValue = report_id; + setup->wIndex = (duration << 8) | intf; + setup->wLength = 0; + + ret = usbh_control_transfer(hport->ep0, setup, NULL); + if (ret < 0) { + return ret; + } + + return 0; +} + +int usbh_hid_get_idle(struct usbh_hubport *hport, uint8_t intf, uint8_t *buffer) +{ + int ret; + struct usb_setup_packet *setup; + struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv; + + setup = hid_class->setup; + + if (hid_class->intf != intf) { + return -1; + } + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = HID_REQUEST_GET_IDLE; + setup->wValue = 0; + setup->wIndex = intf; + setup->wLength = 1; + + ret = usbh_control_transfer(hport->ep0, setup, buffer); + if (ret < 0) { + return ret; + } + + return 0; +} + +USB_NOCACHE_RAM_SECTION uint8_t hid_buffer[128]; + +void usbh_hid_callback(void *arg, int nbytes) +{ + struct usbh_hid *hid_class = (struct usbh_hid *)arg; + + if (nbytes > 0) { + for (size_t i = 0; i < nbytes; i++) { + printf("0x%02x ", hid_buffer[i]); + } + } + + printf("nbytes:%d\r\n", nbytes); +} + +int usbh_hid_connect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usbh_endpoint_cfg ep_cfg = { 0 }; + struct usb_endpoint_descriptor *ep_desc; + char devname[DEV_NAMELEN]; + int ret; + + struct usbh_hid *hid_class = usb_malloc(sizeof(struct usbh_hid)); + if (hid_class == NULL) { + USB_LOG_ERR("Fail to alloc hid_class\r\n"); + return -ENOMEM; + } + memset(hid_class, 0, sizeof(struct usbh_hid)); + + usbh_hid_devno_alloc(hid_class); + usbh_hid_mkdevname(hid_class, devname); + + hport->config.intf[intf].priv = hid_class; + + hid_class->setup = usb_iomalloc(sizeof(struct usb_setup_packet)); + if (hid_class->setup == NULL) { + USB_LOG_ERR("Fail to alloc setup\r\n"); + return -ENOMEM; + } + hid_class->intf = intf; + + ret = usbh_hid_set_idle(hport, intf, 0, 0); + if (ret < 0) { + return ret; + } + + ret = usbh_hid_get_report_descriptor(hport, intf, hid_buffer); + if (ret < 0) { + return ret; + } + + for (uint8_t i = 0; i < hport->config.intf[intf].intf_desc.bNumEndpoints; i++) { + ep_desc = &hport->config.intf[intf].ep[i].ep_desc; + ep_cfg.ep_addr = ep_desc->bEndpointAddress; + ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_interval = ep_desc->bInterval; + ep_cfg.hport = hport; + if (ep_desc->bEndpointAddress & 0x80) { + usbh_ep_alloc(&hid_class->intin, &ep_cfg); + } else { + usbh_ep_alloc(&hid_class->intout, &ep_cfg); + } + } + + USB_LOG_INFO("Register HID Class:%s\r\n", devname); + +#if 1 + ret = usbh_ep_intr_async_transfer(hid_class->intin, hid_buffer, 128, usbh_hid_callback, hid_class); + if (ret < 0) { + return ret; + } +#else + ret = usbh_ep_intr_transfer(hid_class->intin, hid_buffer, 128); + if (ret < 0) { + return ret; + } + USB_LOG_INFO("recv len:%d\r\n", ret); +#endif + return 0; +} + +int usbh_hid_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + char devname[DEV_NAMELEN]; + int ret = 0; + + struct usbh_hid *hid_class = (struct usbh_hid *)hport->config.intf[intf].priv; + + if (hid_class) { + usbh_hid_devno_free(hid_class); + usbh_hid_mkdevname(hid_class, devname); + + if (hid_class->intin) { + ret = usb_ep_cancel(hid_class->intin); + if (ret < 0) { + } + usbh_ep_free(hid_class->intin); + } + + if (hid_class->intout) { + ret = usb_ep_cancel(hid_class->intout); + if (ret < 0) { + } + usbh_ep_free(hid_class->intout); + } + if (hid_class->setup) + usb_iofree(hid_class->setup); + + usb_free(hid_class); + hport->config.intf[intf].priv = NULL; + + USB_LOG_INFO("Unregister HID Class:%s\r\n", devname); + } + + return ret; +} + +const struct usbh_class_driver hid_class_driver = { + .driver_name = "hid", + .connect = usbh_hid_connect, + .disconnect = usbh_hid_disconnect +}; \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbh_hid.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbh_hid.h new file mode 100644 index 00000000..a22c0653 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hid/usbh_hid.h @@ -0,0 +1,45 @@ +/** + * @file usbh_hid.h + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBH_HID_H +#define _USBH_HID_H + +#include "usb_hid.h" + +struct usbh_hid { + struct usb_setup_packet *setup; + uint8_t intf; /* interface number */ + uint8_t minor; + usbh_epinfo_t intin; /* INTR IN endpoint */ + usbh_epinfo_t intout; /* INTR OUT endpoint */ +}; + +extern const struct usbh_class_driver hid_class_driver; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usb_hub.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usb_hub.h new file mode 100644 index 00000000..1beb6f29 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usb_hub.h @@ -0,0 +1,120 @@ +/** + * @file + * @brief USB HUB Device Class public header + * + */ + +#ifndef _USB_HUB_H_ +#define _USB_HUB_H_ + +/* HUB Class Descriptor Types */ +#define HUB_DESCRIPTOR_TYPE_HUB 0x29 + +/* Hub class requests */ +#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS +#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE +#define HUB_REQUEST_SET_FEATURE USB_REQUEST_SET_FEATURE +#define HUB_REQUEST_GET_DESCRIPTOR USB_REQUEST_GET_DESCRIPTOR +#define HUB_REQUEST_SET_DESCRIPTOR USB_REQUEST_SET_DESCRIPTOR +#define HUB_REQUEST_CLEAR_TT_BUFFER (0x08) +#define HUB_REQUEST_RESET_TT (0x09) +#define HUB_REQUEST_GET_TT_STATE (0x0a) +#define HUB_REQUEST_STOP_TT (0x0b) + +/* Hub class features */ +#define HUB_FEATURE_HUB_C_LOCALPOWER (0x0) +#define HUB_FEATURE_HUB_C_OVERCURRENT (0x1) + +/* Port features */ +#define HUB_PORT_FEATURE_CONNECTION (0x00) +#define HUB_PORT_FEATURE_ENABLE (0x01) +#define HUB_PORT_FEATURE_SUSPEND (0x02) +#define HUB_PORT_FEATURE_OVERCURRENT (0x03) +#define HUB_PORT_FEATURE_RESET (0x04) +#define HUB_PORT_FEATURE_L1 (0x05) +#define HUB_PORT_FEATURE_POWER (0x08) +#define HUB_PORT_FEATURE_LOWSPEED (0x09) +#define HUB_PORT_FEATURE_HIGHSPEED (0x0a) +#define HUB_PORT_FEATURE_C_CONNECTION (0x10) +#define HUB_PORT_FEATURE_C_ENABLE (0x11) +#define HUB_PORT_FEATURE_C_SUSPEND (0x12) +#define HUB_PORT_FEATURE_C_OVER_CURREN (0x13) +#define HUB_PORT_FEATURE_C_RESET (0x14) +#define HUB_PORT_FEATURE_TEST (0x15) +#define HUB_PORT_FEATURE_INDICATOR (0x16) +#define HUB_PORT_FEATURE_C_PORTL1 (0x17) + +/* Hub status */ +#define HUB_STATUS_LOCALPOWER (1 << 0) +#define HUB_STATUS_OVERCURRENT (1 << 1) + +/* Hub status change */ +#define HUB_STATUS_C_LOCALPOWER (1 << 0) +#define HUB_STATUS_C_OVERCURRENT (1 << 1) + +/* Hub port status */ +#define HUB_PORT_STATUS_CONNECTION (1 << 0) +#define HUB_PORT_STATUS_ENABLE (1 << 1) +#define HUB_PORT_STATUS_SUSPEND (1 << 2) +#define HUB_PORT_STATUS_OVERCURRENT (1 << 3) +#define HUB_PORT_STATUS_RESET (1 << 4) +#define HUB_PORT_STATUS_L1 (1 << 5) +#define HUB_PORT_STATUS_POWER (1 << 8) +#define HUB_PORT_STATUS_LOW_SPEED (1 << 9) +#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10) +#define HUB_PORT_STATUS_TEST (1 << 11) +#define HUB_PORT_STATUS_INDICATOR (1 << 12) + +/* Hub port status change */ +#define HUB_PORT_STATUS_C_CONNECTION (1 << 0) +#define HUB_PORT_STATUS_C_ENABLE (1 << 1) +#define HUB_PORT_STATUS_C_SUSPEND (1 << 2) +#define HUB_PORT_STATUS_C_OVERCURRENT (1 << 3) +#define HUB_PORT_STATUS_C_RESET (1 << 4) +#define HUB_PORT_STATUS_C_L1 (1 << 5) + +/* Hub characteristics */ +#define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */ +#define HUB_CHAR_LPSM_MASK (3 << HUB_CHAR_LPSM_SHIFT) +#define HUB_CHAR_LPSM_GANGED (0 << HUB_CHAR_LPSM_SHIFT) +#define HUB_CHAR_LPSM_INDIVIDUAL (1 << HUB_CHAR_LPSM_SHIFT) +#define HUB_CHAR_COMPOUND (1 << 2) /* Bit 2: Compound device */ +#define HUB_CHAR_OCPM_SHIFT (3) /* Bits 3-4: Over-current Protection Mode */ +#define HUB_CHAR_OCPM_MASK (3 << HUB_CHAR_OCPM_SHIFT) +#define HUB_CHAR_OCPM_GLOBAL (0 << HUB_CHAR_OCPM_SHIFT) +#define HUB_CHAR_OCPM_INDIVIDUAL (1 << HUB_CHAR_OCPM_SHIFT) +#define HUB_CHAR_TTTT_SHIFT (5) /* Bits 5-6: TT Think Time */ +#define HUB_CHAR_TTTT_MASK (3 << HUB_CHAR_TTTT_SHIFT) +#define HUB_CHAR_TTTT_8_BITS (0 << HUB_CHAR_TTTT_SHIFT) +#define HUB_CHAR_TTTT_16_BITS (1 << HUB_CHAR_TTTT_SHIFT) +#define HUB_CHAR_TTTT_24_BITS (2 << HUB_CHAR_TTTT_SHIFT) +#define HUB_CHAR_TTTT_32_BITS (3 << HUB_CHAR_TTTT_SHIFT) +#define HUB_CHAR_PORTIND (1 << 7) /* Bit 7: Port Indicators Supported */ + +/* Hub descriptor */ +struct usb_hub_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bNbrPorts; + uint16_t wHubCharacteristics; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; + uint8_t PortPwrCtrlMask; +} __PACKED; + +#define USB_SIZEOF_HUB_DESC 9 + +/* Hub status */ +struct hub_status { + uint16_t wPortStatus; + uint16_t wPortChange; +}; + +/* Hub port status */ +struct hub_port_status { + uint16_t wPortStatus; + uint16_t wPortChange; +}; + +#endif /* _USB_HUB_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbd_hub.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbd_hub.c new file mode 100644 index 00000000..99399f69 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbd_hub.c @@ -0,0 +1,106 @@ +/** + * @file usbd_hub.c + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbd_core.h" +#include "usbd_hub.h" + +static struct usb_hub_descriptor hub_desc = { + .bLength = 0x09, + .bDescriptorType = HUB_DESCRIPTOR_TYPE_HUB, + .bNbrPorts = 4, + .wHubCharacteristics = HUB_CHAR_PORTIND | HUB_CHAR_TTTT_32_BITS, + .bPwrOn2PwrGood = 0x32, + .bHubContrCurrent = 0x64, + .DeviceRemovable = 0x00, + .PortPwrCtrlMask = 0xff +}; + +static int hub_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USBD_LOG_DBG("HUB Class Custom request: " + "bRequest 0x%02x\r\n", + setup->bRequest); + + if (((setup->bmRequestType & USB_REQUEST_TYPE_MASK) == USB_REQUEST_CLASS) && + ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_DEVICE) && + (setup->bRequest == HUB_REQUEST_GET_DESCRIPTOR)) { + uint8_t value = (uint8_t)(setup->wValue >> 8); + uint8_t intf_num = (uint8_t)setup->wIndex; + + switch (value) { + case HUB_DESCRIPTOR_TYPE_HUB: + *data = (uint8_t *)&hub_desc; + *len = hub_desc.bLength; + break; + default: + return -1; + } + return 0; + } + + else if (((setup->bmRequestType & USB_REQUEST_TYPE_MASK) == USB_REQUEST_CLASS) && + ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) == USB_REQUEST_RECIPIENT_OTHER)) { + uint8_t hub_port_feature = (uint8_t)(setup->wValue); + uint8_t hub_port = (uint8_t)setup->wIndex; + + switch (setup->bRequest) { + case HUB_REQUEST_GET_STATUS: + break; + case HUB_REQUEST_CLEAR_FEATURE: + break; + case HUB_REQUEST_SET_FEATURE: + break; + default: + USBD_LOG_WRN("Unhandled HUB Class Custom bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + return 0; + } + return -1; +} + +static void hub_notify_handler(uint8_t event, void *arg) +{ + switch (event) { + case USBD_EVENT_RESET: + + break; + default: + break; + } +} + +void usbd_hub_add_interface(usbd_class_t *devclass, usbd_interface_t *intf) +{ + static usbd_class_t *last_class = NULL; + + if (last_class != devclass) { + last_class = devclass; + usbd_class_register(devclass); + } + + intf->class_handler = NULL; + intf->custom_handler = hub_custom_request_handler; + intf->vendor_handler = NULL; + intf->notify_handler = hub_notify_handler; + usbd_class_add_interface(devclass, intf); +} \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbd_hub.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbd_hub.h new file mode 100644 index 00000000..d505c288 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbd_hub.h @@ -0,0 +1,38 @@ +/** + * @file usbd_hub.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBD_HUB_H_ +#define _USBD_HUB_H_ + +#include "usb_hub.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void usbd_hub_add_interface(usbd_class_t *devclass, usbd_interface_t *intf); + +#ifdef __cplusplus +} +#endif + +#endif /* _USBD_HUB_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbh_hub.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbh_hub.c new file mode 100644 index 00000000..77cf334e --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbh_hub.c @@ -0,0 +1,532 @@ +/** + * @file usbh_hub.c + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbh_core.h" +#include "usbh_hub.h" + +#define DEV_FORMAT "/dev/hub%d" +#define DEV_NAMELEN 16 + +static uint32_t g_devinuse = 0; + +usb_slist_t hub_class_head = USB_SLIST_OBJECT_INIT(hub_class_head); + +USB_NOCACHE_RAM_SECTION uint8_t int_buffer[6][USBH_HUB_INTIN_BUFSIZE]; +extern void usbh_external_hport_connect(struct usbh_hubport *hport); +extern void usbh_external_hport_disconnect(struct usbh_hubport *hport); +extern void usbh_hport_activate(struct usbh_hubport *hport); +extern void usbh_hport_deactivate(struct usbh_hubport *hport); + +static void usbh_external_hub_callback(void *arg, int nbytes); + +static inline void usbh_hub_register(struct usbh_hub *hub) +{ + usb_slist_add_tail(&hub_class_head, &hub->list); +} + +static inline void usbh_hub_unregister(struct usbh_hub *hub) +{ + usb_slist_remove(&hub_class_head, &hub->list); +} + +/**************************************************************************** + * Name: usbh_hub_devno_alloc + * + * Description: + * Allocate a unique /dev/hub[n] minor number in the range 2-31. + * + ****************************************************************************/ + +static int usbh_hub_devno_alloc(struct usbh_hub *hub) +{ + uint32_t flags; + int devno; + + flags = usb_osal_enter_critical_section(); + for (devno = 2; devno < 32; devno++) { + uint32_t bitno = 1 << devno; + if ((g_devinuse & bitno) == 0) { + g_devinuse |= bitno; + hub->index = devno; + usb_osal_leave_critical_section(flags); + return 0; + } + } + + usb_osal_leave_critical_section(flags); + return -EMFILE; +} + +/**************************************************************************** + * Name: usbh_hub_devno_free + * + * Description: + * Free a /dev/hub[n] minor number so that it can be used. + * + ****************************************************************************/ + +static void usbh_hub_devno_free(struct usbh_hub *hub) +{ + int devno = hub->index; + + if (devno >= 2 && devno < 32) { + uint32_t flags = usb_osal_enter_critical_section(); + g_devinuse &= ~(1 << devno); + usb_osal_leave_critical_section(flags); + } +} + +/**************************************************************************** + * Name: usbh_hub_mkdevname + * + * Description: + * Format a /dev/hub[n] device name given a minor number. + * + ****************************************************************************/ + +static inline void usbh_hub_mkdevname(struct usbh_hub *hub, char *devname) +{ + snprintf(devname, DEV_NAMELEN, DEV_FORMAT, hub->index); +} + +int usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer) +{ + struct usb_setup_packet *setup; + + setup = hub->setup; + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; + setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8; + setup->wIndex = 0; + setup->wLength = USB_SIZEOF_HUB_DESC; + + return usbh_control_transfer(hub->parent->ep0, setup, buffer); +} + +int usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer) +{ + struct usb_setup_packet *setup; + + setup = hub->setup; + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = HUB_REQUEST_GET_STATUS; + setup->wValue = 0; + setup->wIndex = 0; + setup->wLength = 2; + + return usbh_control_transfer(hub->parent->ep0, setup, buffer); +} + +int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status) +{ + struct usb_setup_packet *setup; + + setup = hub->setup; + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER; + setup->bRequest = HUB_REQUEST_GET_STATUS; + setup->wValue = 0; + setup->wIndex = port; + setup->wLength = 4; + + return usbh_control_transfer(hub->parent->ep0, setup, (uint8_t *)port_status); +} + +int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature) +{ + struct usb_setup_packet *setup; + + setup = hub->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER; + setup->bRequest = HUB_REQUEST_SET_FEATURE; + setup->wValue = feature; + setup->wIndex = port; + setup->wLength = 0; + + return usbh_control_transfer(hub->parent->ep0, setup, NULL); +} + +int usbh_hub_clear_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature) +{ + struct usb_setup_packet *setup; + + setup = hub->setup; + + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_OTHER; + setup->bRequest = HUB_REQUEST_CLEAR_FEATURE; + setup->wValue = feature; + setup->wIndex = port; + setup->wLength = 0; + + return usbh_control_transfer(hub->parent->ep0, setup, NULL); +} + +static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length) +{ + if (desc->bLength != USB_SIZEOF_HUB_DESC) { + USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength); + return -1; + } else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB) { + USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType); + return -2; + } else { + USB_LOG_INFO("Device Descriptor:\r\n"); + USB_LOG_INFO("bLength: 0x%02x \r\n", desc->bLength); + USB_LOG_INFO("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType); + USB_LOG_INFO("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts); + USB_LOG_INFO("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics); + USB_LOG_INFO("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood); + USB_LOG_INFO("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent); + USB_LOG_INFO("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable); + USB_LOG_INFO("PortPwrCtrlMask: 0x%02x \r\n", desc->PortPwrCtrlMask); + } + return 0; +} + +int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usbh_endpoint_cfg ep_cfg = { 0 }; + struct usb_endpoint_descriptor *ep_desc; + char devname[DEV_NAMELEN]; + int ret; + uint8_t *hub_desc_buffer; + struct usbh_hub *hub_class; + + hub_class = usb_malloc(sizeof(struct usbh_hub)); + if (hub_class == NULL) { + USB_LOG_ERR("Fail to alloc hub_class\r\n"); + return -ENOMEM; + } + memset(hub_class, 0, sizeof(struct usbh_hub)); + hub_class->setup = usb_iomalloc(sizeof(struct usb_setup_packet)); + if (hub_class->setup == NULL) { + USB_LOG_ERR("Fail to alloc setup\r\n"); + return -ENOMEM; + } + hub_class->port_status = usb_iomalloc(sizeof(struct hub_port_status)); + if (hub_class->port_status == NULL) { + USB_LOG_ERR("Fail to alloc port_status\r\n"); + return -ENOMEM; + } + + hub_desc_buffer = usb_iomalloc(32); + + usbh_hub_devno_alloc(hub_class); + usbh_hub_mkdevname(hub_class, devname); + + hub_class->dev_addr = hport->dev_addr; + hub_class->parent = hport; + hport->config.intf[0].priv = hub_class; + + ret = usbh_hub_get_hub_descriptor(hub_class, hub_desc_buffer); + if (ret != 0) { + usb_iofree(hub_desc_buffer); + return ret; + } + + parse_hub_descriptor((struct usb_hub_descriptor *)hub_desc_buffer, USB_SIZEOF_HUB_DESC); + memcpy(&hub_class->hub_desc, hub_desc_buffer, USB_SIZEOF_HUB_DESC); + usb_iofree(hub_desc_buffer); + + hub_class->nports = hub_class->hub_desc.bNbrPorts; + + for (uint8_t port = 1; port <= hub_class->nports; port++) { + hub_class->child[port - 1].port = port; + hub_class->child[port - 1].parent = hub_class; + } + + hub_class->int_buffer = int_buffer[hub_class->index - 2]; + usbh_hub_register(hub_class); + + ep_desc = &hport->config.intf[intf].ep[0].ep_desc; + ep_cfg.ep_addr = ep_desc->bEndpointAddress; + ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_interval = ep_desc->bInterval; + ep_cfg.hport = hport; + if (ep_desc->bEndpointAddress & 0x80) { + usbh_ep_alloc(&hub_class->intin, &ep_cfg); + } else { + return -1; + } + + for (uint8_t port = 1; port <= hub_class->nports; port++) { + ret = usbh_hub_set_feature(hub_class, 1, HUB_PORT_FEATURE_POWER); + if (ret < 0) { + return ret; + } + } + + for (uint8_t port = 1; port <= hub_class->nports; port++) { + ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status); + USB_LOG_INFO("Port:%d, status:0x%02x, change:0x%02x\r\n", port, hub_class->port_status->wPortStatus, hub_class->port_status->wPortChange); + if (ret < 0) { + return ret; + } + } + + USB_LOG_INFO("Register HUB Class:%s\r\n", devname); + + ret = usbh_ep_intr_async_transfer(hub_class->intin, hub_class->int_buffer, USBH_HUB_INTIN_BUFSIZE, usbh_external_hub_callback, hub_class); + return 0; +} + +int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usbh_hubport *child; + char devname[DEV_NAMELEN]; + int ret = 0; + + struct usbh_hub *hub_class = (struct usbh_hub *)hport->config.intf[intf].priv; + + if (hub_class) { + usbh_hub_devno_free(hub_class); + usbh_hub_mkdevname(hub_class, devname); + + if (hub_class->intin) { + ret = usb_ep_cancel(hub_class->intin); + if (ret < 0) { + } + usbh_ep_free(hub_class->intin); + } + + if (hub_class->setup) + usb_iofree(hub_class->setup); + if (hub_class->port_status) + usb_iofree(hub_class->port_status); + + for (uint8_t port = 1; port <= hub_class->nports; port++) { + child = &hub_class->child[port - 1]; + usbh_hport_deactivate(child); + for (uint8_t i = 0; i < child->config.config_desc.bNumInterfaces; i++) { + if (child->config.intf[i].class_driver && child->config.intf[i].class_driver->disconnect) { + ret = CLASS_DISCONNECT(child, i); + } + } + + child->config.config_desc.bNumInterfaces = 0; + child->parent = NULL; + } + + usbh_hub_unregister(hub_class); + usb_free(hub_class); + hport->config.intf[intf].priv = NULL; + + USB_LOG_INFO("Unregister HUB Class:%s\r\n", devname); + } + return ret; +} + +static void usbh_extern_hub_psc_event(void *arg) +{ + struct usbh_hub *hub_class; + struct usbh_hubport *connport; + uint8_t port_change; + uint16_t status; + uint16_t change; + uint16_t mask; + uint16_t feat; + uint32_t flags; + int ret; + + hub_class = (struct usbh_hub *)arg; + + /* Has the hub been disconnected? */ + if (!hub_class->parent->connected) { + return; + } + + port_change = hub_class->int_buffer[0]; + USB_LOG_DBG("port_change:0x%02x\r\n", port_change); + + /* Check for status change on any port */ + for (uint8_t port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) { + /* Check if port status has changed */ + if ((port_change & (1 << port)) == 0) { + continue; + } + USB_LOG_DBG("Port %d change\r\n", port); + + /* Port status changed, check what happened */ + port_change &= ~(1 << port); + + /* Read hub port status */ + ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status); + if (ret < 0) { + USB_LOG_ERR("Failed to read port:%d status, errorcode: %d\r\n", port, ret); + continue; + } + status = hub_class->port_status->wPortStatus; + change = hub_class->port_status->wPortChange; + + USB_LOG_DBG("Port:%d, status:0x%02x, change:0x%02x\r\n", port, status, change); + + /* First, clear all change bits */ + mask = 1; + feat = HUB_PORT_FEATURE_C_CONNECTION; + while (change) { + if (change & mask) { + ret = usbh_hub_clear_feature(hub_class, port, feat); + if (ret < 0) { + USB_LOG_ERR("Failed to clear port:%d, change mask:%04x, errorcode:%d\r\n", port, mask, ret); + } + change &= (~mask); + } + mask <<= 1; + feat++; + } + + change = hub_class->port_status->wPortChange; + + /* Handle connect or disconnect, no power management */ + if (change & HUB_PORT_STATUS_C_CONNECTION) { + uint16_t debouncetime = 0; + uint16_t debouncestable = 0; + uint16_t connection = 0xffff; + + /* Debounce */ + while (debouncetime < 1500) { + ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status); + if (ret < 0) { + USB_LOG_ERR("Failed to read port:%d status, errorcode: %d\r\n", port, ret); + break; + } + status = hub_class->port_status->wPortStatus; + change = hub_class->port_status->wPortChange; + + if ((change & HUB_PORT_STATUS_C_CONNECTION) == 0 && + (status & HUB_PORT_STATUS_CONNECTION) == connection) { + debouncestable += 25; + if (debouncestable >= 100) { + USB_LOG_DBG("Port %d debouncestable=%d\r\n", + port, debouncestable); + break; + } + } else { + debouncestable = 0; + connection = status & HUB_PORT_STATUS_CONNECTION; + } + + if ((change & HUB_PORT_STATUS_C_CONNECTION) != 0) { + ret = usbh_hub_clear_feature(hub_class, port, HUB_PORT_FEATURE_C_CONNECTION); + if (ret < 0) { + USB_LOG_ERR("Failed to clear port:%d, change mask:%04x, errorcode:%d\r\n", port, mask, ret); + } + } + debouncetime += 25; + usb_osal_msleep(25); + } + + if (ret < 0 || debouncetime >= 1500) { + USB_LOG_ERR("ERROR: Failed to debounce port %d: %d\r\n", port, ret); + continue; + } + + if (status & HUB_PORT_STATUS_CONNECTION) { + /* Device connected to a port on the hub */ + //USB_LOG_INFO("Connection on port:%d\n", port); + + ret = usbh_hub_set_feature(hub_class, port, HUB_PORT_FEATURE_RESET); + if (ret < 0) { + USB_LOG_ERR("Failed to reset port:%d,errorcode:%d\r\n", port, ret); + continue; + } + + usb_osal_msleep(100); + + ret = usbh_hub_get_portstatus(hub_class, port, hub_class->port_status); + if (ret < 0) { + USB_LOG_ERR("Failed to read port:%d status, errorcode: %d\r\n", port, ret); + continue; + } + status = hub_class->port_status->wPortStatus; + change = hub_class->port_status->wPortChange; + + USB_LOG_DBG("Port:%d, status:0x%02x, change:0x%02x after reset\r\n", port, status, change); + + if ((status & HUB_PORT_STATUS_RESET) == 0 && (status & HUB_PORT_STATUS_ENABLE) != 0) { + if (change & HUB_PORT_STATUS_C_RESET) { + ret = usbh_hub_clear_feature(hub_class, port, HUB_PORT_FEATURE_C_RESET); + if (ret < 0) { + USB_LOG_ERR("Failed to clear port:%d reset change, errorcode: %d\r\n", port, ret); + } + } + connport = &hub_class->child[port - 1]; + + if (status & HUB_PORT_STATUS_HIGH_SPEED) { + connport->speed = USB_SPEED_HIGH; + } else if (status & HUB_PORT_STATUS_LOW_SPEED) { + connport->speed = USB_SPEED_LOW; + } else { + connport->speed = USB_SPEED_FULL; + } + + /* Device connected from a port on the hub, wakeup psc thread. */ + usbh_external_hport_connect(connport); + + } else { + USB_LOG_ERR("Failed to enable port:%d\r\n", port); + continue; + } + } else { + /* Device disconnected from a port on the hub, wakeup psc thread. */ + connport = &hub_class->child[port - 1]; + usbh_external_hport_disconnect(connport); + } + } else { + USB_LOG_WRN("status %04x change %04x not handled\r\n", status, change); + } + } + + /* Check for hub status change */ + + if ((port_change & 1) != 0) { + /* Hub status changed */ + USB_LOG_WRN("Hub status changed, not handled\n"); + } + flags = usb_osal_enter_critical_section(); + if (hub_class->parent->connected) { + ret = usbh_ep_intr_async_transfer(hub_class->intin, hub_class->int_buffer, USBH_HUB_INTIN_BUFSIZE, usbh_external_hub_callback, hub_class); + } + usb_osal_leave_critical_section(flags); +} + +static void usbh_external_hub_callback(void *arg, int nbytes) +{ + struct usbh_hub *hub_class = (struct usbh_hub *)arg; + uint32_t delay = 0; + if (nbytes < 0) { + hub_class->int_buffer[0] = 0; + delay = 100; + } + if (hub_class->parent->connected) { + usb_workqueue_submit(&g_lpworkq, &hub_class->work, usbh_extern_hub_psc_event, (void *)hub_class, delay); + } +} + +const struct usbh_class_driver hub_class_driver = { + .driver_name = "hub", + .connect = usbh_hub_connect, + .disconnect = usbh_hub_disconnect +}; \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbh_hub.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbh_hub.h new file mode 100644 index 00000000..ee0df9e3 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/hub/usbh_hub.h @@ -0,0 +1,42 @@ +/** + * @file usbh_hub.h + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBH_HUB_H_ +#define _USBH_HUB_H_ + +#include "usb_hub.h" + +#define USBH_HUB_MAX_PORTS 4 +/* Maximum size of an interrupt IN transfer */ +#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3) + +extern const struct usbh_class_driver hub_class_driver; +extern usb_slist_t hub_class_head; +extern usb_osal_thread_t hub_thread; +#ifdef __cplusplus +extern "C" { +#endif +int usbh_hub_initialize(void); +#ifdef __cplusplus +} +#endif + +#endif /* _USBH_HUB_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/midi/usb_midi.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/midi/usb_midi.h new file mode 100644 index 00000000..430d75ce --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/midi/usb_midi.h @@ -0,0 +1,174 @@ +/** + * @file + * @brief USB MIDI Class public header + * + */ + +#ifndef _USB_MIDI_H_ +#define _USB_MIDI_H_ + +/* MIDI Streaming class specific interfaces */ +#define MIDI_IN_JACK 0x02 +#define MIDI_OUT_JACK 0x03 + +#define MIDI_JACK_EMBEDDED 0x01 +#define MIDI_JACK_EXTERNAL 0x02 + +#define MIDI_CHANNEL_OMNI 0 +#define MIDI_CHANNEL_OFF 17 + +#define MIDI_PITCHBEND_MIN -8192 +#define MIDI_PITCHBEND_MAX 8191 + +/*! Enumeration of MIDI types */ +enum MidiType { + InvalidType = 0x00, ///< For notifying errors + NoteOff = 0x80, ///< Note Off + NoteOn = 0x90, ///< Note On + AfterTouchPoly = 0xA0, ///< Polyphonic AfterTouch + ControlChange = 0xB0, ///< Control Change / Channel Mode + ProgramChange = 0xC0, ///< Program Change + AfterTouchChannel = 0xD0, ///< Channel (monophonic) AfterTouch + PitchBend = 0xE0, ///< Pitch Bend + SystemExclusive = 0xF0, ///< System Exclusive + TimeCodeQuarterFrame = 0xF1, ///< System Common - MIDI Time Code Quarter Frame + SongPosition = 0xF2, ///< System Common - Song Position Pointer + SongSelect = 0xF3, ///< System Common - Song Select + TuneRequest = 0xF6, ///< System Common - Tune Request + Clock = 0xF8, ///< System Real Time - Timing Clock + Start = 0xFA, ///< System Real Time - Start + Continue = 0xFB, ///< System Real Time - Continue + Stop = 0xFC, ///< System Real Time - Stop + ActiveSensing = 0xFE, ///< System Real Time - Active Sensing + SystemReset = 0xFF, ///< System Real Time - System Reset +}; + +/*! Enumeration of Thru filter modes */ +enum MidiFilterMode { + Off = 0, ///< Thru disabled (nothing passes through). + Full = 1, ///< Fully enabled Thru (every incoming message is sent back). + SameChannel = 2, ///< Only the messages on the Input Channel will be sent back. + DifferentChannel = 3, ///< All the messages but the ones on the Input Channel will be sent back. +}; + +/*! \brief Enumeration of Control Change command numbers. + See the detailed controllers numbers & description here: + http://www.somascape.org/midi/tech/spec.html#ctrlnums + */ +enum MidiControlChangeNumber { + // High resolution Continuous Controllers MSB (+32 for LSB) ---------------- + BankSelect = 0, + ModulationWheel = 1, + BreathController = 2, + // CC3 undefined + FootController = 4, + PortamentoTime = 5, + DataEntry = 6, + ChannelVolume = 7, + Balance = 8, + // CC9 undefined + Pan = 10, + ExpressionController = 11, + EffectControl1 = 12, + EffectControl2 = 13, + // CC14 undefined + // CC15 undefined + GeneralPurposeController1 = 16, + GeneralPurposeController2 = 17, + GeneralPurposeController3 = 18, + GeneralPurposeController4 = 19, + + // Switches ---------------------------------------------------------------- + Sustain = 64, + Portamento = 65, + Sostenuto = 66, + SoftPedal = 67, + Legato = 68, + Hold = 69, + + // Low resolution continuous controllers ----------------------------------- + SoundController1 = 70, ///< Synth: Sound Variation FX: Exciter On/Off + SoundController2 = 71, ///< Synth: Harmonic Content FX: Compressor On/Off + SoundController3 = 72, ///< Synth: Release Time FX: Distortion On/Off + SoundController4 = 73, ///< Synth: Attack Time FX: EQ On/Off + SoundController5 = 74, ///< Synth: Brightness FX: Expander On/Off + SoundController6 = 75, ///< Synth: Decay Time FX: Reverb On/Off + SoundController7 = 76, ///< Synth: Vibrato Rate FX: Delay On/Off + SoundController8 = 77, ///< Synth: Vibrato Depth FX: Pitch Transpose On/Off + SoundController9 = 78, ///< Synth: Vibrato Delay FX: Flange/Chorus On/Off + SoundController10 = 79, ///< Synth: Undefined FX: Special Effects On/Off + GeneralPurposeController5 = 80, + GeneralPurposeController6 = 81, + GeneralPurposeController7 = 82, + GeneralPurposeController8 = 83, + PortamentoControl = 84, + // CC85 to CC90 undefined + Effects1 = 91, ///< Reverb send level + Effects2 = 92, ///< Tremolo depth + Effects3 = 93, ///< Chorus send level + Effects4 = 94, ///< Celeste depth + Effects5 = 95, ///< Phaser depth + + // Channel Mode messages --------------------------------------------------- + AllSoundOff = 120, + ResetAllControllers = 121, + LocalControl = 122, + AllNotesOff = 123, + OmniModeOff = 124, + OmniModeOn = 125, + MonoModeOn = 126, + PolyModeOn = 127 +}; + +struct midi_cs_interface_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t SubType; + uint16_t bcdADC; + uint16_t wTotalLength; +} __PACKED; + +struct midi_in_jack_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t SubType; + uint8_t bJackType; + uint8_t bJackId; + uint8_t iJack; +} __PACKED; + +struct midi_out_jack_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t SubType; + uint8_t bJackType; + uint8_t bJackId; + uint8_t bNrInputPins; + uint8_t baSourceId; + uint8_t baSourcePin; + uint8_t iJack; +} __PACKED; + +#define MIDI_ADAPTER_AC_INTERFACE_DESCRIPTOR_SIZE(num) (8 + num) +#define MIDI_ADAPTER_AC_INTERFACE_DESCRIPTOR(num) \ + struct midi_adapter_ac_interface_descriptor { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t SubType; \ + uint16_t bcdADC; \ + uint16_t wTotalLength; \ + uint8_t bInCollection; \ + uint8_t baInterfaceNr[num]; \ + } __PACKED + +#define MIDI_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(num) (4 + num) +#define MIDI_CS_BULK_ENDPOINT_DESCRIPTOR(num) \ + struct midi_cs_bulk_descriptor { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t SubType; \ + uint8_t bNumEmbMIDIJack; \ + uint8_t baAssocJackID[num]; \ + } __PACKED + +#endif /* _USB_MIDI_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usb_msc.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usb_msc.h new file mode 100644 index 00000000..d7b353e2 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usb_msc.h @@ -0,0 +1,121 @@ +/** + * @file + * @brief USB Mass Storage Class public header + * + * Header follows the Mass Storage Class Specification + * (Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf) and + * Mass Storage Class Bulk-Only Transport Specification + * (usbmassbulk_10.pdf). + * Header is limited to Bulk-Only Transfer protocol. + */ + +#ifndef _USB_MSC_H__ +#define _USB_MSC_H__ + +/* MSC Subclass Codes */ +#define MSC_SUBCLASS_RBC 0x01 /* Reduced block commands (e.g., flash devices) */ +#define MSC_SUBCLASS_SFF8020I_MMC2 0x02 /* SFF-8020i/MMC-2 (ATAPI) (e.g., C/DVD) */ +#define MSC_SUBCLASS_QIC157 0x03 /* QIC-157 (e.g., tape device) */ +#define MSC_SUBCLASS_UFI 0x04 /* e.g. floppy device */ +#define MSC_SUBCLASS_SFF8070I 0x05 /* SFF-8070i (e.g. floppy disk) */ +#define MSC_SUBCLASS_SCSI 0x06 /* SCSI transparent */ + +/* MSC Protocol Codes */ +#define MSC_PROTOCOL_CBI_INT 0x00 /* CBI transport with command completion interrupt */ +#define MSC_PROTOCOL_CBI_NOINT 0x01 /* CBI transport without command completion interrupt */ +#define MSC_PROTOCOL_BULK_ONLY 0x50 /* Bulk only transport */ + +/* MSC Request Codes */ +#define MSC_REQUEST_RESET 0xFF +#define MSC_REQUEST_GET_MAX_LUN 0xFE + +/** MSC Command Block Wrapper (CBW) Signature */ +#define MSC_CBW_Signature 0x43425355 +/** Bulk-only Command Status Wrapper (CSW) Signature */ +#define MSC_CSW_Signature 0x53425355 + +/** MSC Command Block Status Values */ +#define CSW_STATUS_CMD_PASSED 0x00 +#define CSW_STATUS_CMD_FAILED 0x01 +#define CSW_STATUS_PHASE_ERROR 0x02 + +#define MSC_MAX_CDB_LEN (16) /* Max length of SCSI Command Data Block */ + +/** MSC Bulk-Only Command Block Wrapper (CBW) */ +struct CBW { + uint32_t dSignature; /* 'USBC' = 0x43425355 */ + uint32_t dTag; /* Depends on command id */ + uint32_t dDataLength; /* Number of bytes that host expects to transfer */ + uint8_t bmFlags; /* Bit 7: Direction=IN (other obsolete or reserved) */ + uint8_t bLUN; /* LUN (normally 0) */ + uint8_t bCBLength; /* len of cdb[] */ + uint8_t CB[MSC_MAX_CDB_LEN]; /* Command Data Block */ +} __PACKED; + +#define USB_SIZEOF_MSC_CBW 31 + +/** MSC Bulk-Only Command Status Wrapper (CSW) */ +struct CSW { + uint32_t dSignature; /* 'USBS' = 0x53425355 */ + uint32_t dTag; /* Same tag as original command */ + uint32_t dDataResidue; /* Amount not transferred */ + uint8_t bStatus; /* Status of transfer */ +} __PACKED; + +#define USB_SIZEOF_MSC_CSW 13 + +/*Length of template descriptor: 23 bytes*/ +#define MSC_DESCRIPTOR_LEN (9 + 7 + 7) +// clang-format off +#ifndef CONFIG_USB_HS +#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep,str_idx) \ + /* Interface */ \ + 0x09, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ + bFirstInterface, /* bInterfaceNumber */ \ + 0x00, /* bAlternateSetting */ \ + 0x02, /* bNumEndpoints */ \ + USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \ + MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ \ + MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ \ + str_idx, /* iInterface */ \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + out_ep, /* bEndpointAddress */ \ + 0x02, /* bmAttributes */ \ + 0x40, 0x00, /* wMaxPacketSize */ \ + 0x00, /* bInterval */ \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + in_ep, /* bEndpointAddress */ \ + 0x02, /* bmAttributes */ \ + 0x40, 0x00, /* wMaxPacketSize */ \ + 0x00 /* bInterval */ +#else +#define MSC_DESCRIPTOR_INIT(bFirstInterface, out_ep, in_ep,str_idx) \ + /* Interface */ \ + 0x09, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ + bFirstInterface, /* bInterfaceNumber */ \ + 0x00, /* bAlternateSetting */ \ + 0x02, /* bNumEndpoints */ \ + USB_DEVICE_CLASS_MASS_STORAGE, /* bInterfaceClass */ \ + MSC_SUBCLASS_SCSI, /* bInterfaceSubClass */ \ + MSC_PROTOCOL_BULK_ONLY, /* bInterfaceProtocol */ \ + str_idx, /* iInterface */ \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + out_ep, /* bEndpointAddress */ \ + 0x02, /* bmAttributes */ \ + 0x00, 0x02, /* wMaxPacketSize */ \ + 0x00, /* bInterval */ \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + in_ep, /* bEndpointAddress */ \ + 0x02, /* bmAttributes */ \ + 0x00, 0x02, /* wMaxPacketSize */ \ + 0x00 /* bInterval */ +#endif +// clang-format on + +#endif /* USB_MSC_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usb_scsi.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usb_scsi.h new file mode 100644 index 00000000..86811c3e --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usb_scsi.h @@ -0,0 +1,986 @@ +/**************************************************************************** + * include/nuttx/scsi.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SCSI_H +#define __INCLUDE_NUTTX_SCSI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* SCSI commands ************************************************************/ + +#define SCSI_CMD_TESTUNITREADY 0x00 +#define SCSI_CMD_REZEROUNIT 0x01 +#define SCSI_CMD_REQUESTSENSE 0x03 +#define SCSI_CMD_FORMAT_UNIT 0x04 +#define SCSI_CMD_REASSIGNBLOCKS 0x07 +#define SCSI_CMD_READ6 0x08 +#define SCSI_CMD_WRITE6 0x0a +#define SCSI_CMD_SEEK6 0x0b +#define SCSI_CMD_SPACE6 0x11 +#define SCSI_CMD_INQUIRY 0x12 +#define SCSI_CMD_MODESELECT6 0x15 +#define SCSI_CMD_RESERVE6 0x16 +#define SCSI_CMD_RELEASE6 0x17 +#define SCSI_CMD_COPY 0x18 +#define SCSI_CMD_MODESENSE6 0x1a +#define SCSI_CMD_STARTSTOPUNIT 0x1b +#define SCSI_CMD_RECEIVEDIAGNOSTICRESULTS 0x1c +#define SCSI_CMD_SENDDIAGNOSTIC 0x1d +#define SCSI_CMD_PREVENTMEDIAREMOVAL 0x1e +#define SCSI_CMD_READFORMATCAPACITIES 0x23 +#define SCSI_CMD_READCAPACITY10 0x25 +#define SCSI_CMD_READ10 0x28 +#define SCSI_CMD_WRITE10 0x2a +#define SCSI_CMD_SEEK10 0x2b +#define SCSI_CMD_WRITEANDVERIFY 0x2e +#define SCSI_CMD_VERIFY10 0x2f +#define SCSI_CMD_SEARCHDATAHIGH 0x30 +#define SCSI_CMD_SEARCHDATAEQUAL 0x31 +#define SCSI_CMD_SEARCHDATALOW 0x32 +#define SCSI_CMD_SETLIMITS10 0x33 +#define SCSI_CMD_PREFETCH10 0x34 +#define SCSI_CMD_SYNCHCACHE10 0x35 +#define SCSI_CMD_LOCKCACHE 0x36 +#define SCSI_CMD_READDEFECTDATA10 0x37 +#define SCSI_CMD_COMPARE 0x39 +#define SCSI_CMD_COPYANDVERIFY 0x3a +#define SCSI_CMD_WRITEBUFFER 0x3b +#define SCSI_CMD_READBUFFER 0x3c +#define SCSI_CMD_READLONG10 0x3e +#define SCSI_CMD_WRITELONG10 0x3f +#define SCSI_CMD_CHANGEDEFINITION 0x40 +#define SCSI_CMD_WRITESAME10 0x41 +#define SCSI_CMD_LOGSELECT 0x4c +#define SCSI_CMD_LOGSENSE 0x4d +#define SCSI_CMD_XDWRITE10 0x50 +#define SCSI_CMD_XPWRITE10 0x51 +#define SCSI_CMD_XDREAD10 0x52 +#define SCSI_CMD_MODESELECT10 0x55 +#define SCSI_CMD_RESERVE10 0x56 +#define SCSI_CMD_RELEASE10 0x57 +#define SCSI_CMD_MODESENSE10 0x5a +#define SCSI_CMD_PERSISTENTRESERVEIN 0x5e +#define SCSI_CMD_PERSISTENTRESERVEOUT 0x5f +#define SCSI_CMD_32 0x7f +#define SCSI_CMD_XDWRITEEXTENDED 0x80 +#define SCSI_CMD_REBUILD 0x82 +#define SCSI_CMD_REGENERATE 0x82 +#define SCSI_CMD_EXTENDEDCOPY 0x83 +#define SCSI_CMD_COPYRESULTS 0x84 +#define SCSI_CMD_ACCESSCONTROLIN 0x86 +#define SCSI_CMD_ACCESSCONTROLOUT 0x87 +#define SCSI_CMD_READ16 0x88 +#define SCSI_CMD_WRITE16 0x8a +#define SCSI_CMD_READATTRIBUTE 0x8c +#define SCSI_CMD_WRITEATTRIBUTE 0x8d +#define SCSI_CMD_WRITEANDVERIFY16 0x8e +#define SCSI_CMD_PREFETCH16 0x90 +#define SCSI_CMD_SYNCHCACHE16 0x91 +#define SCSI_CMD_LOCKUNLOCKACACHE 0x92 +#define SCSI_CMD_WRITESAME16 0x93 +#define SCSI_CMD_READCAPACITY16 0x9e +#define SCSI_CMD_READLONG16 0x9e +#define SCSI_CMD_WRITELONG106 0x9f +#define SCSI_CMD_REPORTLUNS 0xa0 +#define SCSI_CMD_MAINTENANCEIN 0xa3 +#define SCSI_CMD_MAINTENANCEOUT 0xa4 +#define SCSI_CMD_MOVEMEDIUM 0xa5 +#define SCSI_CMD_MOVEMEDIUMATTACHED 0xa7 +#define SCSI_CMD_READ12 0xa8 +#define SCSI_CMD_WRITE12 0xaa +#define SCSI_CMD_READMEDIASERIALNUMBER 0xab +#define SCSI_CMD_WRITEANDVERIFY12 0xae +#define SCSI_CMD_VERIFY12 0xaf +#define SCSI_CMD_SETLIMITS12 0xb3 +#define SCSI_CMD_READELEMENTSTATUS 0xb4 +#define SCSI_CMD_READDEFECTDATA12 0xb7 +#define SCSI_CMD_REDUNDANCYGROUPIN 0xba +#define SCSI_CMD_REDUNDANCYGROUPOUT 0xbb +#define SCSI_CMD_SPAREIN 0xbc +#define SCSI_CMD_SPAREOUT 0xbd +#define SCSI_CMD_VOLUMESETIN 0xbe +#define SCSI_CMD_VOLUMESETOUT 0xbf + +/* Common SCSI KCQ values (sense Key/additional sense Code/ASC Qualifier) *** + * + * 0xnn0386 Write Fault Data Corruption + * 0xnn0500 Illegal request + * 0xnn0600 Unit attention + * 0xnn0700 Data protect + * 0xnn0800 LUN communication failure + * 0xnn0801 LUN communication timeout + * 0xnn0802 LUN communication parity error + * 0xnn0803 LUN communication CRC error + * 0xnn0900 vendor specific sense key + * 0xnn0901 servo fault + * 0xnn0904 head select fault + * 0xnn0a00 error log overflow + * 0xnn0b00 aborted command + * 0xnn0c00 write error + * 0xnn0c02 write error - auto-realloc failed + * 0xnn0e00 data miscompare + * 0xnn1200 address mark not founf for ID field + * 0xnn1400 logical block not found + * 0xnn1500 random positioning error + * 0xnn1501 mechanical positioning error + * 0xnn1502 positioning error detected by read of medium + * 0xnn2700 write protected + * 0xnn2900 POR or bus reset occurred + * 0xnn3101 format failed + * 0xnn3191 format corrupted + * 0xnn3201 defect list update error + * 0xnn3202 no spares available + * 0xnn3501 unspecified enclosure services failure + * 0xnn3700 parameter rounded + * 0xnn3d00 invalid bits in identify message + * 0xnn3e00 LUN not self-configured yet + * 0xnn4001 DRAM parity error + * 0xnn4002 DRAM parity error + * 0xnn4200 power-on or self-test failure + * 0xnn4c00 LUN failed self-configuration + * 0xnn5c00 RPL status change + * 0xnn5c01 spindles synchronized + * 0xnn5c02 spindles not synchronized + * 0xnn6500 voltage fault + * 0xnn8000 general firmware error + */ + +/* No sense KCQ values */ + +#define SCSI_KCQ_NOSENSE 0x000000 /* No error */ +#define SCSI_KCQ_PFATHRESHOLDREACHED 0x005c00 /* No sense - PFA threshold reached */ + +/* Soft error KCQ values */ + +#define SCSI_KCQSE_RWENOINDEX 0x010100 /* Recovered Write error - no index */ +#define SCSI_KCQSE_RECOVEREDNOSEEKCOMPLETION 0x010200 /* Recovered no seek completion */ +#define SCSI_KCQSE_RWEWRITEFAULT 0x010300 /* Recovered Write error - write fault */ +#define SCSI_KCQSE_TRACKFOLLOWINGERROR 0x010900 /* Track following error */ +#define SCSI_KCQSE_TEMPERATUREWARNING 0x010b01 /* Temperature warning */ +#define SCSI_KCQSE_RWEWARREALLOCATED 0x010c01 /* Recovered Write error with auto-realloc - reallocated */ +#define SCSI_KCQSE_RWERECOMMENDREASSIGN 0x010c03 /* Recovered Write error - recommend reassign */ +#define SCSI_KCQSE_RDWOEUSINGPREVLBI 0x011201 /* Recovered data without ECC using prev logical block ID */ +#define SCSI_KCQSE_RDWEUSINGPREVLBI 0x011202 /* Recovered data with ECC using prev logical block ID */ +#define SCSI_KCQSE_RECOVEREDRECORDNOTFOUND 0x011401 /* Recovered Record Not Found */ +#define SCSI_KCQSE_RWEDSME 0x011600 /* Recovered Write error - Data Sync Mark Error */ +#define SCSI_KCQSE_RWEDSEDATAREWRITTEN 0x011601 /* Recovered Write error - Data Sync Error - data rewritten */ +#define SCSI_KCQSE_RWEDSERECOMMENDREWRITE 0x011602 /* Recovered Write error - Data Sync Error - recommend rewrite */ +#define SCSI_KCQSE_RWEDSEDATAAUTOREALLOCATED 0x011603 /* Recovered Write error - Data Sync Error - data auto-reallocated */ +#define SCSI_KCQSE_RWEDSERECOMMENDREASSIGNMENT 0x011604 /* Recovered Write error - Data Sync Error - recommend reassignment */ +#define SCSI_KCQSE_RDWNECORRECTIONAPPLIED 0x011700 /* Recovered data with no error correction applied */ +#define SCSI_KCQSE_RREWITHRETRIES 0x011701 /* Recovered Read error - with retries */ +#define SCSI_KCQSE_RDUSINGPOSITIVEOFFSET 0x011702 /* Recovered data using positive offset */ +#define SCSI_KCQSE_RDUSINGNEGATIVEOFFSET 0x011703 /* Recovered data using negative offset */ +#define SCSI_KCQSE_RDUSINGPREVIOUSLBI 0x011705 /* Recovered data using previous logical block ID */ +#define SCSI_KCQSE_RREWOEAUTOREALLOCATED 0x011706 /* Recovered Read error - without ECC, auto reallocated */ +#define SCSI_KCQSE_RREWOERECOMMENDREASSIGN 0x011707 /* Recovered Read error - without ECC, recommend reassign */ +#define SCSI_KCQSE_RREWOERECOMMENDREWRITE 0x011708 /* Recovered Read error - without ECC, recommend rewrite */ +#define SCSI_KCQSE_RREWOEDATAREWRITTEN 0x011709 /* Recovered Read error - without ECC, data rewritten */ +#define SCSI_KCQSE_RREWE 0x011800 /* Recovered Read error - with ECC */ +#define SCSI_KCQSE_RDWEANDRETRIES 0x011801 /* Recovered data with ECC and retries */ +#define SCSI_KCQSE_RREWEAUTOREALLOCATED 0x011802 /* Recovered Read error - with ECC, auto reallocated */ +#define SCSI_KCQSE_RREWERECOMMENDREASSIGN 0x011805 /* Recovered Read error - with ECC, recommend reassign */ +#define SCSI_KCQSE_RDUSINGECCANDOFFSETS 0x011806 /* Recovered data using ECC and offsets */ +#define SCSI_KCQSE_RREWEDATAREWRITTEN 0x011807 /* Recovered Read error - with ECC, data rewritten */ +#define SCSI_KCQSE_DLNOTFOUND 0x011c00 /* Defect List not found */ +#define SCSI_KCQSE_PRIMARYDLNOTFOUND 0x011c01 /* Primary defect list not found */ +#define SCSI_KCQSE_GROWNDLNOTFOUND 0x011c02 /* Grown defect list not found */ +#define SCSI_KCQSE_PARTIALDLTRANSFERRED 0x011f00 /* Partial defect list transferred */ +#define SCSI_KCQSE_INTERNALTARGETFAILURE 0x014400 /* Internal target failure */ +#define SCSI_KCQSE_PFATHRESHOLDREACHED 0x015d00 /* PFA threshold reached */ +#define SCSI_KCQSE_PFATESTWARNING 0x015dff /* PFA test warning */ +#define SCSI_KCQSE_INTERNALLOGICFAILURE 0x018100 /* Internal logic failure */ + +/* Not Ready / Diagnostic Failure KCQ values */ + +#define SCSI_KCQNR_CAUSENOTREPORTABLE 0x020400 /* Not Ready - Cause not reportable. */ +#define SCSI_KCQNR_BECOMINGREADY 0x020401 /* Not Ready - becoming ready */ +#define SCSI_KCQNR_NEEDINITIALIZECOMMAND 0x020402 /* Not Ready - need initialize command (start unit) */ +#define SCSI_KCQNR_MANUALINTERVENTIONREQUIRED 0x020403 /* Not Ready - manual intervention required */ +#define SCSI_KCQNR_FORMATINPROGRESS 0x020404 /* Not Ready - format in progress */ +#define SCSI_KCQNR_SELFTESTINPROGRESS 0x020409 /* Not Ready - self-test in progress */ +#define SCSI_KCQNR_MEDIUMFORMATCORRUPTED 0x023100 /* Not Ready - medium format corrupted */ +#define SCSI_KCQNR_FORMATCOMMANDFAILED 0x023101 /* Not Ready - format command failed */ +#define SCSI_KCQNR_ESUNAVAILABLE 0x023502 /* Not Ready - enclosure services unavailable */ +#define SCSI_KCQNR_MEDIANOTPRESENT 0x023a00 /* Not Ready - media not present */ +#define SCSI_KCQDF_BRINGUPFAILORDEGRADEDMODE 0x024080 /* Diagnostic Failure - bring-up fail or degraded mode */ +#define SCSI_KCQDF_HARDDISKCONTROLLER 0x024081 /* Diagnostic Failure - Hard Disk Controller */ +#define SCSI_KCQDF_RAMMICROCODENOTLOADED 0x024085 /* Diagnostic Failure - RAM microcode not loaded */ +#define SCSI_KCQDF_RROCALIBRATION 0x024090 /* Diagnostic Failure - RRO Calibration */ +#define SCSI_KCQDF_CHANNELCALIBRATION 0x024091 /* Diagnostic Failure - Channel Calibration */ +#define SCSI_KCQDF_HEADLOAD 0x024092 /* Diagnostic Failure - Head Load */ +#define SCSI_KCQDF_WRITEAE 0x024093 /* Diagnostic Failure - Write AE */ +#define SCSI_KCQDF_12VOVERCURRENT 0x024094 /* Diagnostic Failure - 12V over current */ +#define SCSI_KCQDF_OTHERSPINDLEFAILURE 0x024095 /* Diagnostic Failure - Other spindle failure */ +#define SCSI_KCQDF_SELFRESET 0x0240b0 /* Diagnostic Failure - self-reset */ +#define SCSI_KCQDF_CONFIGNOTLOADED 0x024c00 /* Diagnostic Failure - config not loaded */ + +/* Medium error KCQ values */ + +#define SCSI_KCQME_WRITEFAULT 0x030300 /* Medium Error - write fault */ +#define SCSI_KCQME_WRITEFAULTAUTOREALLOCFAILED 0x030c02 /* Medium Error - write error - auto-realloc failed */ +#define SCSI_KCQME_WRITERTLIMITEXCEEDED 0x030cbb /* Medium Error - write recovery time limit exceeded */ +#define SCSI_KCQME_IDCRCERROR 0x031000 /* Medium Error - ID CRC error */ +#define SCSI_KCQME_UNRRE1 0x031100 /* Medium Error - unrecovered read error */ +#define SCSI_KCQME_READRETRIESEXHAUSTED 0x031101 /* Medium Error - read retries exhausted */ +#define SCSI_KCQME_ERRORTOOLONGTOCORRECT 0x031102 /* Medium Error - error too long to correct */ +#define SCSI_KCQME_UREAUTOREALLOCFAILED 0x031104 /* Medium Error - unrecovered read error - auto re-alloc failed */ +#define SCSI_KCQME_URERECOMMENDREASSIGN 0x03110b /* Medium Error - unrecovered read error - recommend reassign */ +#define SCSI_KCQME_READRTLIMITEXCEEDED 0x0311ff /* Medium Error - read recovery time limit exceeded */ +#define SCSI_KCQME_RECORDNOTFOUND 0x031401 /* Medium Error - record not found */ +#define SCSI_KCQME_DSME 0x031600 /* Medium Error - Data Sync Mark error */ +#define SCSI_KCQME_DSERECOMMENDREASSIGN 0x031604 /* Medium Error - Data Sync Error - recommend reassign */ +#define SCSI_KCQME_DLE 0x031900 /* Medium Error - defect list error */ +#define SCSI_KCQME_DLNOTAVAILABLE 0x031901 /* Medium Error - defect list not available */ +#define SCSI_KCQME_DLEINPRIMARYLIST 0x031902 /* Medium Error - defect list error in primary list */ +#define SCSI_KCQME_DLEINGROWNLIST 0x031903 /* Medium Error - defect list error in grown list */ +#define SCSI_KCQME_FEWERTHAN50PCTDLCOPIES 0x03190e /* Medium Error - fewer than 50% defect list copies */ +#define SCSI_KCQME_MEDIUMFORMATCORRUPTED 0x033100 /* Medium Error - medium format corrupted */ +#define SCSI_KCQME_FORMATCOMMANDFAILED 0x033101 /* Medium Error - format command failed */ +#define SCSI_KCQME_DATAAUTOREALLOCATED 0x038000 /* Medium Error - data auto-reallocated */ + +/* Hardware Error KCQ values */ + +#define SCSI_KCQHE_NOINDEXORSECTOR 0x040100 /* Hardware Error - no index or sector */ +#define SCSI_KCQHE_NOSEEKCOMPLETE 0x040200 /* Hardware Error - no seek complete */ +#define SCSI_KCQHE_WRITEFAULT 0x040300 /* Hardware Error - write fault */ +#define SCSI_KCQHE_COMMUNICATIONFAILURE 0x040800 /* Hardware Error - communication failure */ +#define SCSI_KCQHE_TRACKFOLLOWINGERROR 0x040900 /* Hardware Error - track following error */ +#define SCSI_KCQHE_UREINRESERVEDAREA 0x041100 /* Hardware Error - unrecovered read error in reserved area */ +#define SCSI_KCQHE_DSMEINRESERVEDAREA 0x041600 /* Hardware Error - Data Sync Mark error in reserved area */ +#define SCSI_KCQHE_DLE 0x041900 /* Hardware Error - defect list error */ +#define SCSI_KCQHE_DLEINPRIMARYLIST 0x041902 /* Hardware Error - defect list error in Primary List */ +#define SCSI_KCQHE_DLEINGROWNLIST 0x041903 /* Hardware Error - defect list error in Grown List */ +#define SCSI_KCQHE_REASSIGNFAILED 0x043100 /* Hardware Error - reassign failed */ +#define SCSI_KCQHE_NODEFECTSPAREAVAILABLE 0x043200 /* Hardware Error - no defect spare available */ +#define SCSI_KCQHE_UNSUPPORTEDENCLOSUREFUNCTION 0x043501 /* Hardware Error - unsupported enclosure function */ +#define SCSI_KCQHE_ESUNAVAILABLE 0x043502 /* Hardware Error - enclosure services unavailable */ +#define SCSI_KCQHE_ESTRANSFERFAILURE 0x043503 /* Hardware Error - enclosure services transfer failure */ +#define SCSI_KCQHE_ESREFUSED 0x043504 /* Hardware Error - enclosure services refused */ +#define SCSI_KCQHE_SELFTESTFAILED 0x043e03 /* Hardware Error - self-test failed */ +#define SCSI_KCQHE_UNABLETOUPDATESELFTEST 0x043e04 /* Hardware Error - unable to update self-test */ +#define SCSI_KCQHE_DMDIAGNOSTICFAIL 0x044080 /* Hardware Error - Degrade Mode. Diagnostic Fail */ +#define SCSI_KCQHE_DMHWERROR 0x044081 /* Hardware Error - Degrade Mode. H/W Error */ +#define SCSI_KCQHE_DMRAMMICROCODENOTLOADED 0x044085 /* Hardware Error - Degrade Mode. RAM microcode not loaded */ +#define SCSI_KCQHE_SEEKTESTFAILURE 0x044090 /* Hardware Error - seek test failure */ +#define SCSI_KCQHE_READWRITETESTFAILURE 0x0440a0 /* Hardware Error - read/write test failure */ +#define SCSI_KCQHE_DEVICESELFRESET 0x0440b0 /* Hardware Error - device self-reset */ +#define SCSI_KCQHE_COMPONENTMISMATCH 0x0440d0 /* Hardware Error - component mismatch */ +#define SCSI_KCQHE_INTERNALTARGETFAILURE 0x044400 /* Hardware Error - internal target failure */ +#define SCSI_KCQHE_INTERNALLOGICERROR 0x048100 /* Hardware Error - internal logic error */ +#define SCSI_KCQHE_COMMANDTIMEOUT 0x048200 /* Hardware Error - command timeout */ + +/* Illegal Request KCQ values */ + +#define SCSI_KCQIR_PARMLISTLENGTHERROR 0x051a00 /* Illegal Request - parm list length error */ +#define SCSI_KCQIR_INVALIDCOMMAND 0x052000 /* Illegal Request - invalid/unsupported command code */ +#define SCSI_KCQIR_LBAOUTOFRANGE 0x052100 /* Illegal Request - LBA out of range */ +#define SCSI_KCQIR_INVALIDFIELDINCBA 0x052400 /* Illegal Request - invalid field in CDB (Command Descriptor Block) */ +#define SCSI_KCQIR_INVALIDLUN 0x052500 /* Illegal Request - invalid LUN */ +#define SCSI_KCQIR_INVALIDFIELDSINPARMLIST 0x052600 /* Illegal Request - invalid fields in parm list */ +#define SCSI_KCQIR_PARAMETERNOTSUPPORTED 0x052601 /* Illegal Request - parameter not supported */ +#define SCSI_KCQIR_INVALIDPARMVALUE 0x052602 /* Illegal Request - invalid parm value */ +#define SCSI_KCQIR_IFPTHRESHOLDPARAMETER 0x052603 /* Illegal Request - invalid field parameter - threshold parameter */ +#define SCSI_KCQIR_INVALIDRELEASEOFPR 0x052604 /* Illegal Request - invalid release of persistent reservation */ +#define SCSI_KCQIR_IFPTMSFIRMWARETAG 0x052697 /* Illegal Request - invalid field parameter - TMS firmware tag */ +#define SCSI_KCQIR_IFPCHECKSUM 0x052698 /* Illegal Request - invalid field parameter - check sum */ +#define SCSI_KCQIR_IFPFIRMWARETAG 0x052699 /* Illegal Request - invalid field parameter - firmware tag */ +#define SCSI_KCQIR_COMMANDSEQUENCEERROR 0x052c00 /* Illegal Request - command sequence error */ +#define SCSI_KCQIR_UNSUPPORTEDENCLOSUREFUNCTION 0x053501 /* Illegal Request - unsupported enclosure function */ +#define SCSI_KCQIR_SAVINGPARMSNOTSUPPORTED 0x053900 /* Illegal Request - Saving parameters not supported */ +#define SCSI_KCQIR_INVALIDMESSAGE 0x054900 /* Illegal Request - invalid message */ +#define SCSI_KCQIR_MEDIALOADOREJECTFAILED 0x055300 /* Illegal Request - media load or eject failed */ +#define SCSI_KCQIR_UNLOADTAPEFAILURE 0x055301 /* Illegal Request - unload tape failure */ +#define SCSI_KCQIR_MEDIUMREMOVALPREVENTED 0x055302 /* Illegal Request - medium removal prevented */ +#define SCSI_KCQIR_SYSTEMRESOURCEFAILURE 0x055500 /* Illegal Request - system resource failure */ +#define SCSI_KCQIR_SYSTEMBUFFERFULL 0x055501 /* Illegal Request - system buffer full */ +#define SCSI_KCQIR_INSUFFICIENTRR 0x055504 /* Illegal Request - Insufficient Registration Resources */ + +/* Unit Attention KCQ values */ + +#define SCSI_KCQUA_NOTREADYTOTRANSITION 0x062800 /* Unit Attention - not-ready to ready transition (format complete) */ +#define SCSI_KCQUA_DEVICERESETOCCURRED 0x062900 /* Unit Attention - POR or device reset occurred */ +#define SCSI_KCQUA_POROCCURRED 0x062901 /* Unit Attention - POR occurred */ +#define SCSI_KCQUA_SCSIBUSRESETOCCURRED 0x062902 /* Unit Attention - SCSI bus reset occurred */ +#define SCSI_KCQUA_TARGETRESETOCCURRED 0x062903 /* Unit Attention - TARGET RESET occurred */ +#define SCSI_KCQUA_SELFINITIATEDRESETOCCURRED 0x062904 /* Unit Attention - self-initiated-reset occurred */ +#define SCSI_KCQUA_TRANSCEIVERMODECHANGETOSE 0x062905 /* Unit Attention - transceiver mode change to SE */ +#define SCSI_KCQUA_TRANSCEIVERMODECHANGETOLVD 0x062906 /* Unit Attention - transceiver mode change to LVD */ +#define SCSI_KCQUA_PARAMETERSCHANGED 0x062a00 /* Unit Attention - parameters changed */ +#define SCSI_KCQUA_MODEPARAMETERSCHANGED 0x062a01 /* Unit Attention - mode parameters changed */ +#define SCSI_KCQUA_LOGSELECTPARMSCHANGED 0x062a02 /* Unit Attention - log select parms changed */ +#define SCSI_KCQUA_RESERVATIONSPREEMPTED 0x062a03 /* Unit Attention - Reservations pre-empted */ +#define SCSI_KCQUA_RESERVATIONSRELEASED 0x062a04 /* Unit Attention - Reservations released */ +#define SCSI_KCQUA_REGISTRATIONSPREEMPTED 0x062a05 /* Unit Attention - Registrations pre-empted */ +#define SCSI_KCQUA_COMMANDSCLEARED 0x062f00 /* Unit Attention - commands cleared by another initiator */ +#define SCSI_KCQUA_OPERATINGCONDITIONSCHANGED 0x063f00 /* Unit Attention - target operating conditions have changed */ +#define SCSI_KCQUA_MICROCODECHANGED 0x063f01 /* Unit Attention - microcode changed */ +#define SCSI_KCQUA_CHANGEDOPERATINGDEFINITION 0x063f02 /* Unit Attention - changed operating definition */ +#define SCSI_KCQUA_INQUIRYPARAMETERSCHANGED 0x063f03 /* Unit Attention - inquiry parameters changed */ +#define SCSI_KCQUA_DEVICEIDENTIFIERCHANGED 0x063f05 /* Unit Attention - device identifier changed */ +#define SCSI_KCQUA_INVALIDAPMPARAMETERS 0x063f90 /* Unit Attention - invalid APM parameters */ +#define SCSI_KCQUA_WORLDWIDENAMEMISMATCH 0x063f91 /* Unit Attention - world-wide name mismatch */ +#define SCSI_KCQUA_PFATHRESHOLDREACHED 0x065d00 /* Unit Attention - PFA threshold reached */ +#define SCSI_KCQUA_PFATHRESHOLDEXCEEDED 0x065dff /* Unit Attention - PFA threshold exceeded */ + +/* Write Protect KCQ values */ + +#define SCSI_KCQWP_COMMANDNOTALLOWED 0x072700 /* Write Protect - command not allowed */ + +/* Aborted Command KCQ values */ + +#define SCSI_KCQAC_NOADDITIONALSENSECODE 0x0b0000 /* Aborted Command - no additional sense code */ +#define SCSI_KCQAC_SYNCDATATRANSFERERROR 0x0b1b00 /* Aborted Command - sync data transfer error (extra ACK) */ +#define SCSI_KCQAC_UNSUPPORTEDLUN 0x0b2500 /* Aborted Command - unsupported LUN */ +#define SCSI_KCQAC_ECHOBUFFEROVERWRITTEN 0x0b3f0f /* Aborted Command - echo buffer overwritten */ +#define SCSI_KCQAC_MESSAGEREJECTERROR 0x0b4300 /* Aborted Command - message reject error */ +#define SCSI_KCQAC_INTERNALTARGETFAILURE 0x0b4400 /* Aborted Command - internal target failure */ +#define SCSI_KCQAC_SELECTIONFAILURE 0x0b4500 /* Aborted Command - Selection/Reselection failure */ +#define SCSI_KCQAC_SCSIPARITYERROR 0x0b4700 /* Aborted Command - SCSI parity error */ +#define SCSI_KCQAC_INITIATORDETECTEDERRORECEIVED 0x0b4800 /* Aborted Command - initiator-detected error message received */ +#define SCSI_KCQAC_ILLEGALMESSAGE 0x0b4900 /* Aborted Command - inappropriate/illegal message */ +#define SCSI_KCQAC_DATAPHASEERROR 0x0b4b00 /* Aborted Command - data phase error */ +#define SCSI_KCQAC_OVERLAPPEDCOMMANDSATTEMPTED 0x0b4e00 /* Aborted Command - overlapped commands attempted */ +#define SCSI_KCQAC_LOOPINITIALIZATION 0x0b4f00 /* Aborted Command - due to loop initialization */ + +/* Other KCQ values: */ + +#define SCSO_KCQOTHER_MISCOMPARE 0x0e1d00 /* Miscompare - during verify byte check operation */ + +/* SSCSI Status Codes *******************************************************/ + +#define SCSI_STATUS_OK 0x00 /* OK */ +#define SCSI_STATUS_CHECKCONDITION 0x02 /* Check condition */ +#define SCSI_STATUS_CONDITIONMET 0x04 /* Condition met */ +#define SCSI_STATUS_BUSY 0x08 /* Busy */ +#define SCSI_STATUS_INTERMEDIATE 0x10 /* Intermediate */ +#define SCSI_STATUS_DATAOVERUNDERRUN 0x12 /* Data Under/Over Run? */ +#define SCSI_STATUS_INTERMEDIATECONDITIONMET 0x14 /* Intermediate - Condition met */ +#define SCSI_STATUS_RESERVATIONCONFLICT 0x18 /* Reservation conflict */ +#define SCSI_STATUS_COMMANDTERMINATED 0x22 /* Command terminated */ +#define SCSI_STATUS_QUEUEFULL 0x28 /* Queue (task set) full */ +#define SCSI_STATUS_ACAACTIVE 0x30 /* ACA active */ +#define SCSI_STATUS_TASKABORTED 0x40 /* Task aborted */ + +/* Definitions for selected SCSI commands ***********************************/ + +/* Inquiry */ + +#define SCSICMD_INQUIRYFLAGS_EVPD 0x01 /* Bit 0: EVPD */ + /* Bits 5-7: Peripheral Qualifier */ +#define SCSIRESP_INQUIRYPQ_CONNECTED 0x00 /* 000: Device is connected */ +#define SCSIRESP_INQUIRYPQ_NOTCONNECTED 0x20 /* 001: Device is NOT connected */ +#define SCSIRESP_INQUIRYPQ_NOTCAPABLE 0x60 /* 011: LUN not supported */ + /* Bits 0-4: Peripheral Device */ +#define SCSIRESP_INQUIRYPD_DIRECTACCESS 0x00 /* Direct-access block device */ +#define SCSIRESP_INQUIRYPD_SEQUENTIALACCESS 0x01 /* Sequential-access block device */ +#define SCSIRESP_INQUIRYPD_PRINTER 0x02 /* Printer device */ +#define SCSIRESP_INQUIRYPD_PROCESSOR 0x03 /* Processor device */ +#define SCSIRESP_INQUIRYPD_WRONCE 0x04 /* Write once device */ +#define SCSIRESP_INQUIRYPD_CDDVD 0x05 /* CD/DVD device */ +#define SCSIRESP_INQUIRYPD_SCANNER 0x06 /* Scanner device (obsolete) */ +#define SCSIRESP_INQUIRYPD_OPTICAL 0x07 /* Optical memory device */ +#define SCSIRESP_INQUIRYPD_MEDIUMCHANGER 0x08 /* Medium changer device (Jukebox) */ +#define SCSIRESP_INQUIRYPD_COMMUNICATIONS 0x09 /* Communications device (obsolete) */ +#define SCSIRESP_INQUIRYPD_STORAGEARRAY 0x0c /* Storage array controller device */ +#define SCSIRESP_INQUIRYPD_ENCLOSURESERVICES 0x0d /* Enclosure services device */ +#define SCSIRESP_INQUIRYPD_RBC 0x0e /* Simplified direct-access device */ +#define SCSIRESP_INQUIRYPD_OCRW 0x0f /* Optical reader/writer device */ +#define SCSIRESP_INQUIRYPD_BCC 0x10 /* Bridge controller commands */ +#define SCSIRESP_INQUIRYPD_OSD 0x11 /* Object-based storage device */ +#define SCSIRESP_INQUIRYPD_ADC 0x12 /* Automation/drive interface */ +#define SCSIRESP_INQUIRYPD_WKLU 0x1e /* Well-known logical unit */ +#define SCSIRESP_INQUIRYPD_UNKNOWN 0x1f /* Direct-access block device */ + +#define SCSIRESP_INQUIRYFLAGS1_RMB 0x80 /* Bit 7: RMB */ +#define SCSIRESP_INQUIRYFLAGS2_NORMACA 0x20 /* Bit 5: NormACA */ +#define SCSIRESP_INQUIRYFLAGS2_HISUP 0x10 /* Bit 4: HiSup */ +#define SCSIRESP_INQUIRYFLAGS2_FMTMASK 0x0f /* Bits 0-3: Response data format */ + +#define SCSIRESP_INQUIRYFLAGS3_SCCS 0x80 /* Bit 8: SCCS */ +#define SCSIRESP_INQUIRYFLAGS3_ACC 0x40 /* Bit 7: ACC */ +#define SCSIRESP_INQUIRYFLAGS3_TPGSMASK 0x30 /* Bits 4-5: TPGS */ +#define SCSIRESP_INQUIRYFLAGS3_3PC 0x08 /* Bit 3: 3PC */ +#define SCSIRESP_INQUIRYFLAGS3_PROTECT 0x01 /* Bit 0: Protect */ + +#define SCSIRESP_INQUIRYFLAGS4_BQUE 0x80 /* Bit 7: BQue */ +#define SCSIRESP_INQUIRYFLAGS4_ENCSERV 0x40 /* Bit 6: EncServ */ +#define SCSIRESP_INQUIRYFLAGS4_VS 0x20 /* Bit 5: VS */ +#define SCSIRESP_INQUIRYFLAGS4_MULTIP 0x10 /* Bit 4: MultIP */ +#define SCSIRESP_INQUIRYFLAGS4_MCHNGR 0x08 /* Bit 3: MChngr */ +#define SCSIRESP_INQUIRYFLAGS4_ADDR16 0x01 /* Bit 0: Addr16 */ + +#define SCSIRESP_INQUIRYFLAGS5_WBUS16 0x20 /* Bit 5: WBus16 */ +#define SCSIRESP_INQUIRYFLAGS5_SYNC 0x10 /* Bit 4: SYNC */ +#define SCSIRESP_INQUIRYFLAGS5_LINKED 0x08 /* Bit 3: LINKED */ +#define SCSIRESP_INQUIRYFLAGS5_CMDQUEUE 0x02 /* Bit 1: CmdQue */ +#define SCSIRESP_INQUIRYFLAGS5_VS 0x01 /* Bit 0: VS */ + +#define SCSIRESP_INQUIRYFLAGS6_CLOCKINGMASK 0xc0 /* Bits 2-3: Clocking */ +#define SCSIRESP_INQUIRYFLAGS6_QAS 0x02 /* Bit 1: QAS */ +#define SCSIRESP_INQUIRYFLAGS6_IUS 0x01 /* Bit 0: IUS */ + +/* Sense data */ + +/* Sense data response codes */ + +#define SCSIRESP_SENSEDATA_CURRENTFIXED 0x70 /* Byte 1 is always the response code */ +#define SCSIRESP_SENSEDATA_DEFERREDFIXED 0x71 +#define SCSIRESP_SENSEDATA_CURRENTDESC 0x72 +#define SCSIRESP_SENSEDATA_DEFERREDDESC 0x73 + +#define SCSIRESP_SENSEDATA_RESPVALID 0x80 + +/* Fixed sense data flags */ + +#define SCSIRESP_SENSEDATA_FILEMARK 0x80 /* Bit 7: FileMark */ +#define SCSIRESP_SENSEDATA_EOM 0x40 /* Bit 6: EOM */ +#define SCSIRESP_SENSEDATA_ILI 0x20 /* Bit 5: ILI */ +#define SCSIRESP_SENSEDATA_SENSEKEYMASK 0x0f /* Bits 0-3: Sense key */ +#define SCSIRESP_SENSEDATA_NOSENSE 0x00 /* Nothing to be reported */ +#define SCSIRESP_SENSEDATA_RECOVEREDERROR 0x01 /* Successful after recovery action */ +#define SCSIRESP_SENSEDATA_NOTREADY 0x02 /* Logical unit is not accessible */ +#define SCSIRESP_SENSEDATA_MEDIUMERROR 0x03 /* Error possibly caused by flaw in medium */ +#define SCSIRESP_SENSEDATA_HARDWAREERROR 0x04 /* Non-recoverable hardware error */ +#define SCSIRESP_SENSEDATA_ILLEGALREQUEST 0x05 /* Error in received request */ +#define SCSIRESP_SENSEDATA_UNITATTENTION 0x06 /* Unit attention condition */ +#define SCSIRESP_SENSEDATA_DATAPROTECT 0x07 /* Action failed, medium protected */ +#define SCSIRESP_SENSEDATA_BLANKCHECK 0x08 /* Encountered blank media */ +#define SCSIRESP_SENSEDATA_VENDORSPECIFIC 0x09 /* Vendor specific condition */ +#define SCSIRESP_SENSEDATA_ABORTEDCOMMAND 0x0b /* Command was aborted */ + +#define SCSIRESP_SENSEDATA_KEYVALID 0x80 /* Sense-specific data valid */ + +/* Mode Select 6 */ + +#define SCSICMD_MODESELECT6_PF 0x10 /* Bit 4: PF */ +#define SCSICMD_MODESELECT6_SP 0x01 /* Bit 0: SP */ + +/* Mode Sense 6 */ + +#define SCSICMD_MODESENSE6_DBD 0x08 /* Bit 3: PF */ + +#define SCSICMD_MODESENSE_PCMASK 0xc0 /* Bits 6-7: Page control (PC) */ +#define SCSICMD_MODESENSE_PCCURRENT 0x00 /* Current values */ +#define SCSICMD_MODESENSE_PCCHANGEABLE 0x40 /* Changeable values */ +#define SCSICMD_MODESENSE_PCDEFAULT 0x80 /* Default values */ +#define SCSICMD_MODESENSE_PCSAVED 0xc0 /* Saved values */ +#define SCSICMD_MODESENSE_PGCODEMASK 0x3f /* Bits 0-5: Page code */ + +#define SCSICMD_MODESENSE6_PCDEFAULT 0x80 /* Default values */ + /* Direct-access device page codes */ +#define SCSIRESP_MODESENSE_PGCCODE_VENDOR 0x00 /* Vendor-specific */ +#define SCSIRESP_MODESENSE_PGCCODE_RWERROR 0x01 /* Read/Write error recovery mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_RECONNECT 0x02 /* Disconnect-reconnect mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_FORMATDEV 0x03 /* Format device mode page (obsolete) */ +#define SCSIRESP_MODESENSE_PGCCODE_RIGID 0x04 /* Rigid disk geometry mode page (obsolete) */ +#define SCSIRESP_MODESENSE_PGCCODE_FLEXIBLE 0x05 /* Flexible disk geometry mode page (obsolete) */ +#define SCSIRESP_MODESENSE_PGCCODE_VERIFY 0x07 /* Verify error recovery mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_CACHING 0x08 /* Caching mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_CONTROL 0x0a /* Control mode page (0x0a/0x00) */ +#define SCSIRESP_MODESENSE_PGCCODE_CONTROLEXT 0x0a /* Control extension mode page (0x0a/0x01) */ +#define SCSIRESP_MODESENSE_PGCCODE_MEDIUMTYPES 0x0b /* Medum types supported mode page (obsolete) */ +#define SCSIRESP_MODESENSE_PGCCODE_NP 0x0c /* Notch and partition mode page (obsolete) */ +#define SCSIRESP_MODESENSE_PGCCODE_XOR 0x10 /* XOR control mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_ES 0x14 /* Enclosure services mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_PSLUN 0x18 /* Protocol-specific LUN mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_PSPORT 0x19 /* Protocol-specific port mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_POWER 0x1a /* Power condition mode page */ +#define SCSIRESP_MODESENSE_PGCCODE_IE 0x1c /* Informational exceptions control mode page (0x1c/0x00) */ +#define SCSIRESP_MODESENSE_PGCCODE_BC 0x1c /* Background control mode page (0x1c/0x01) */ +#define SCSIRESP_MODESENSE_PGCCODE_RETURNALL 0x3f /* Return all mode pages */ + /* Direct-access caching mode page */ +#define SCSIRESP_CACHINGMODEPG_PS 0x80 /* Byte 0, Bit 7: PS */ +#define SCSIRESP_CACHINGMODEPG_SPF 0x60 /* Byte 0, Bit 6: SPF */ +#define SCSIRESP_CACHINGMODEPG_IC 0x80 /* Byte 2, Bit 7: IC */ +#define SCSIRESP_CACHINGMODEPG_ABPF 0x40 /* Byte 2, Bit 6: ABPF */ +#define SCSIRESP_CACHINGMODEPG_CAP 0x20 /* Byte 2, Bit 5: CAP */ +#define SCSIRESP_CACHINGMODEPG_DISC 0x10 /* Byte 2, Bit 4: DISC */ +#define SCSIRESP_CACHINGMODEPG_SIZE 0x08 /* Byte 2, Bit 3: SIZE */ +#define SCSIRESP_CACHINGMODEPG_WCE 0x04 /* Byte 2, Bit 2: Write cache enable (WCE) */ +#define SCSIRESP_CACHINGMODEPG_MF 0x02 /* Byte 2, Bit 1: MF */ +#define SCSIRESP_CACHINGMODEPG_RCD 0x01 /* Byte 2, Bit 0: Read cache disable (RCD) */ + +#define SCSIRESP_MODEPARMHDR_DAPARM_WP 0x80 /* Bit 7: WP (Direct-access block devices only) */ +#define SCSIRESP_MODEPARMHDR_DAPARM_DBPFUA 0x10 /* Bit 4: DBOFUA (Direct-access block devices only) */ + +#define SCSIRESP_PAGEFMT_PS 0x80 /* Bit 7: PS */ +#define SCSIRESP_PAGEFMT_SPF 0x40 /* Bit 6: SPF */ +#define SCSIRESP_PAGEFMT_PGCODEMASK 0x3f /* Bits 0-5: Page code */ + +/* Prevent / Allow Medium Removal */ + +#define SCSICMD_PREVENTMEDIUMREMOVAL_TRANSPORT 0x01 /* Removal prohibited from data transport */ +#define SCSICMD_PREVENTMEDIUMREMOVAL_MCHANGER 0x02 /* Removal prohibited from medium changer */ + +/* Read format capacities */ + +#define SCIRESP_RDFMTCAPACITIES_UNFORMATED 0x01 /* Unformatted media */ +#define SCIRESP_RDFMTCAPACITIES_FORMATED 0x02 /* Formatted media */ +#define SCIRESP_RDFMTCAPACITIES_NOMEDIA 0x03 /* No media */ + +/* Read 6 */ + +#define SCSICMD_READ6_MSLBAMASK 0x1f + +/* Write 6 */ + +#define SCSICMD_WRITE6_MSLBAMASK 0x1f + +/* Mode Select 10 */ + +#define SCSICMD_MODESELECT10_PF 0x10 /* Bit 4: PF */ +#define SCSICMD_MODESELECT10_SP 0x01 /* Bit 0: SP */ + +/* Mode Sense 10 */ + +#define SCSICMD_MODESENSE10_LLBAA 0x10 /* Bit 4: LLBAA */ +#define SCSICMD_MODESENSE10_DBD 0x08 /* Bit 3: PF */ + +/* Read 10 */ + +#define SCSICMD_READ10FLAGS_RDPROTECTMASK 0xe0 +#define SCSICMD_READ10FLAGS_DPO 0x10 /* Disable Page Out */ +#define SCSICMD_READ10FLAGS_FUA 0x08 +#define SCSICMD_READ10FLAGS_FUANV 0x02 + +/* Write 10 */ + +#define SCSICMD_WRITE10FLAGS_WRPROTECTMASK 0xe0 +#define SCSICMD_WRITE10FLAGS_DPO 0x10 /* Disable Page Out */ +#define SCSICMD_WRITE10FLAGS_FUA 0x08 +#define SCSICMD_WRITE10FLAGS_FUANV 0x02 + +/* Verify 10 */ + +#define SCSICMD_VERIFY10_VRPROTECTMASK 0xe0 /* Byte 1: Bits 5-7: VRPROTECT */ +#define SCSICMD_VERIFY10_DPO 0x10 /* Byte 1: Bit 4: Disable Page Out (DPO) */ +#define SCSICMD_VERIFY10_BYTCHK 0x02 /* Byte 1: Bit 2: BytChk */ + +/* Read 12 */ + +#define SCSICMD_READ12FLAGS_RDPROTECTMASK 0xe0 +#define SCSICMD_READ12FLAGS_DPO 0x10 /* Disable Page Out */ +#define SCSICMD_READ12FLAGS_FUA 0x08 +#define SCSICMD_READ12FLAGS_FUANV 0x02 + +/* Write 12 */ + +#define SCSICMD_WRITE12FLAGS_WRPROTECTMASK 0xe0 +#define SCSICMD_WRITE12FLAGS_DPO 0x10 /* Disable Page Out */ +#define SCSICMD_WRITE12FLAGS_FUA 0x08 +#define SCSICMD_WRITE12FLAGS_FUANV 0x02 + +/* Verify 12 */ + +#define SCSICMD_VERIFY12_VRPROTECTMASK 0xe0 /* Byte 1: Bits 5-7: VRPROTECT */ +#define SCSICMD_VERIFY12_DPO 0x10 /* Byte 1: Bit 4: Disable Page Out (DPO) */ +#define SCSICMD_VERIFY12_BYTCHK 0x02 /* Byte 1: Bit 2: BytChk */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Format structures for selected SCSI primary commands */ + +#define SCSICMD_TESTUNITREADY_SIZEOF 6 + +struct scsicmd_requestsense_s +{ + uint8_t opcode; /* 0: 0x03 */ + uint8_t flags; /* 1: See SCSICMD_REQUESTSENSE_FLAGS_* */ + uint8_t reserved[2]; /* 2-3: Reserved */ + uint8_t alloclen; /* 4: Allocation length */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_REQUESTSENSE_SIZEOF 6 +#define SCSICMD_REQUESTSENSE_MSSIZEOF 12 /* MS-Windows REQUEST SENSE with cbw->cdblen == 12 */ + +struct scsiresp_fixedsensedata_s +{ + uint8_t code; /* 0: Response code See SCSIRESP_SENSEDATA_*FIXED defns */ + uint8_t obsolete; /* 1: */ + uint8_t flags; /* 2: See SCSIRESP_SENSEDATA_* definitions */ + uint8_t info[4]; /* 3-6: Information */ + uint8_t len; /* 7: Additional length */ + uint8_t cmdinfo[4]; /* 8-11: Command-specific information */ + uint8_t code2; /* 12: Additional sense code */ + uint8_t qual2; /* 13: Additional sense code qualifier */ + uint8_t fru; /* 14: Field replacement unit code */ + uint8_t key[3]; /* 15-17: Sense key specific */ + /* 18-: Additional bytes may follow */ +}; +#define SCSIRESP_FIXEDSENSEDATA_SIZEOF 18 /* Minimum size */ + +struct scscicmd_inquiry_s +{ + uint8_t opcode; /* 0: 0x12 */ + uint8_t flags; /* 1: See SCSICMD_INQUIRY_FLAGS_* */ + uint8_t pagecode; /* 2: Page code */ + uint8_t alloclen[2]; /* 3-4: Allocation length */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_INQUIRY_SIZEOF 6 + +struct scsiresp_inquiry_s +{ + /* Mandatory */ + + uint8_t qualtype; /* 0: Bits 5-7: Peripheral qualifier; Bits 0-4: Peripheral device type */ + uint8_t flags1; /* 1: See SCSIRESP_INQUIRY_FLAGS1_* */ + uint8_t version; /* 2: Version */ + uint8_t flags2; /* 3: See SCSIRESP_INQUIRY_FLAGS2_* */ + uint8_t len; /* 4: Additional length */ + uint8_t flags3; /* 5: See SCSIRESP_INQUIRY_FLAGS3_* */ + uint8_t flags4; /* 6: See SCSIRESP_INQUIRY_FLAGS4_* */ + uint8_t flags5; /* 7: See SCSIRESP_INQUIRY_FLAGS5_* */ + uint8_t vendorid[8]; /* 8-15: T10 Vendor Identification */ + uint8_t productid[16]; /* 16-31: Product Identification */ + uint8_t revision[4]; /* 32-35: Product Revision Level */ + + /* Optional */ + + uint8_t vendor[20]; /* 36-55: Vendor specific */ + uint8_t flags6; /* 56: See SCSIRESP_INQUIRY_FLAGS6_* */ + uint8_t reserved1; /* 57: Reserved */ + uint8_t version1[2]; /* 58-59: Version Descriptor 1 */ + uint8_t version2[2]; /* 60-61: Version Descriptor 2 */ + uint8_t version3[2]; /* 62-63: Version Descriptor 3 */ + uint8_t version4[2]; /* 64-65: Version Descriptor 4 */ + uint8_t version5[2]; /* 66-67: Version Descriptor 5 */ + uint8_t version6[2]; /* 68-69: Version Descriptor 6 */ + uint8_t version7[2]; /* 70-71: Version Descriptor 7 */ + uint8_t version8[2]; /* 72-73: Version Descriptor 8 */ + uint8_t reserved2[22]; /* 74-95: Reserved */ + /* 96-: Vendor-specific parameters may follow */ +}; +#define SCSIRESP_INQUIRY_SIZEOF 36 /* Minimum size */ + +struct scsicmd_modeselect6_s +{ + uint8_t opcode; /* 0x15 */ + uint8_t flags; /* 1: See SCSICMD_MODESELECT6_FLAGS_* */ + uint8_t reserved[2]; /* 2-3: Reserved */ + uint8_t plen; /* 4: Parameter list length */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_MODESELECT6_SIZEOF 6 + +struct scsicmd_modesense6_s +{ + uint8_t opcode; /* 0x1a */ + uint8_t flags; /* 1: See SCSICMD_MODESENSE6_FLAGS_* */ + uint8_t pcpgcode; /* 2: Bits 6-7: PC, bits 0-5: page code */ + uint8_t subpgcode; /* 3: subpage code */ + uint8_t alloclen; /* 4: Allocation length */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_MODESENSE6_SIZEOF 6 + +struct scsiresp_modeparameterhdr6_s +{ + uint8_t mdlen; /* 0: Mode data length */ + uint8_t type; /* 1: Medium type */ + uint8_t param; /* 2: Device-specific parameter */ + uint8_t bdlen; /* 3: Block descriptor length */ +}; +#define SCSIRESP_MODEPARAMETERHDR6_SIZEOF 4 + +struct scsiresp_blockdesc_s +{ + uint8_t density; /* 0: density code */ + uint8_t nblocks[3]; /* 1-3: Number of blocks */ + uint8_t reserved; /* 4: reserved */ + uint8_t blklen[3]; /* 5-7: Block len */ +}; +#define SCSIRESP_BLOCKDESC_SIZEOF 8 + +struct scsiresp_pageformat_s +{ + uint8_t pgcode; /* 0: See SCSIRESP_PAGEFMT_* definitions */ + uint8_t pglen; /* 1: Page length (n-1) */ + uint8_t parms[1]; /* 2-n: Mode parameters */ +}; + +struct scsiresp_subpageformat_s +{ + uint8_t pgcode; /* 0: See SCSIRESP_PAGEFMT_* definitions */ + uint8_t subpgcode; /* 1: sub-page code */ + uint8_t pglen[2]; /* 2-3: Page length (n-3) */ + uint8_t parms[1]; /* 4-n: Mode parameters */ +}; + +struct scsiresp_cachingmodepage_s +{ + uint8_t pgcode; /* 0: Bit 7: PS; Bit 6: SPF, Bits 0-5: page code == 8 */ + uint8_t len; /* 1: Page length (18) */ + uint8_t flags1; /* 2: See SCSIRESP_CACHINGMODEPG_* definitions */ + uint8_t priority; /* 3: Bits 4-7: Demand read retention priority; Bits 0-3: Write retention priority */ + uint8_t dpflen[2]; /* 4-5: Disable prefetch transfer length */ + uint8_t minpf[2]; /* 6-7: Minimum pre-fetch */ + uint8_t maxpf[2]; /* 8-9: Maximum pre-fetch */ + uint8_t maxpfc[2]; /* 10-11: Maximum pref-fetch ceiling */ + uint8_t flags2; /* 12: See SCSIRESP_CACHINGMODEPG_* definitions */ + uint8_t nsegments; /* 13: Number of cache segments */ + uint8_t segsize[2]; /* 14-15: Cache segment size */ + uint8_t reserved; /* 16: Reserved */ + uint8_t obsolete[3]; /* 17-19: Obsolete */ +}; + +/* Format structures for selected SCSI block commands */ + +struct scsicmd_read6_s +{ + uint8_t opcode; /* 0: 0x08 */ + uint8_t mslba; /* 1: Bits 5-7: reserved; Bits 0-6: MS Logical Block Address (LBA) */ + uint8_t lslba[2]; /* 2-3: LS Logical Block Address (LBA) */ + uint8_t xfrlen; /* 4: Transfer length (in contiguous logical blocks) */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_READ6_SIZEOF 6 + +struct scsicmd_write6_s +{ + uint8_t opcode; /* 0: 0x0a */ + uint8_t mslba; /* 1: Bits 5-7: reserved; Bits 0-6: MS Logical Block Address (LBA) */ + uint8_t lslba[2]; /* 2-3: LS Logical Block Address (LBA) */ + uint8_t xfrlen; /* 4: Transfer length (in contiguous logical blocks) */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_WRITE6_SIZEOF 6 + +struct scsicmd_startstopunit_s +{ + uint8_t opcode; /* 0: 0x1b */ + uint8_t immed; /* 1: Bits 2-7: Reserved, Bit 0: Immed */ + uint8_t reserved; /* 2: reserved */ + uint8_t pcm; /* 3: Bits 4-7: Reserved, Bits 0-3: Power condition modifier */ + uint8_t pc; /* 4: Bits 4-7: Power condition, Bit 2: NO_FLUSH, Bit 1: LOEJ, Bit 0: START */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_STARTSTOPUNIT_SIZEOF 6 + +struct scsicmd_preventmediumremoval_s +{ + uint8_t opcode; /* 0: 0x1e */ + uint8_t reserved[3]; /* 1-3: Reserved */ + uint8_t prevent; /* 4: Bits 2-7: Reserved, Bits 0:1: prevent */ + uint8_t control; /* 5: Control */ +}; +#define SCSICMD_PREVENTMEDIUMREMOVAL_SIZEOF 6 + +struct scsicmd_readformatcapcacities_s +{ + uint8_t opcode; /* 0: 0x23 */ + uint8_t reserved[6]; /* 1-6: Reserved */ + uint8_t alloclen[2]; /* 7-8: Allocation length */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_READFORMATCAPACITIES_SIZEOF 10 + +struct scsiresp_readformatcapacities_s +{ + /* Current capacity header */ + + uint8_t reserved[3]; /* 0-2: Reserved */ + uint8_t listlen; /* 3: Capacity list length */ + + /* Current/Maximum Capacity Descriptor (actually a separate structure) */ + + uint8_t nblocks[4]; /* 4-7: Number of blocks */ + uint8_t type; /* 8: Bits 2-7: Reserved, Bits 0-1: Descriptor type */ + uint8_t blocklen[3]; /* 9-11: Block length */ +}; +#define SCSIRESP_READFORMATCAPACITIES_SIZEOF 12 +#define SCSIRESP_CURRCAPACITYDESC_SIZEOF 8 + +struct scsiresp_formattedcapacitydesc_s +{ + uint8_t nblocks[4]; /* 0-3: Number of blocks */ + uint8_t type; /* 4: Bits 2-7: Type, bits 0-1, reserved */ + uint8_t param[3]; /* 5-7: Type dependent parameter */ +}; +#define SCSIRESP_FORMATTEDCAPACITYDESC_SIZEOF 8 + +struct scsicmd_readcapacity10_s +{ + uint8_t opcode; /* 0: 0x25 */ + uint8_t reserved1; /* 1: Bits 1-7: Reserved, Bit 0: Obsolete */ + uint8_t lba[4]; /* 2-5: Logical block address (LBA) */ + uint8_t reserved2[2]; /* 6-7: Reserved */ + uint8_t pmi; /* 8: Bits 1-7 Reserved; Bit 0: PMI */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_READCAPACITY10_SIZEOF 10 + +struct scsiresp_readcapacity10_s +{ + uint8_t lba[4]; /* 0-3: Returned logical block address (LBA) */ + uint8_t blklen[4]; /* 4-7: Logical block length (in bytes) */ +}; +#define SCSIRESP_READCAPACITY10_SIZEOF 8 + +struct scsicmd_read10_s +{ + uint8_t opcode; /* 0: 0x28 */ + uint8_t flags; /* 1: See SCSICMD_READ10FLAGS_* */ + uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */ + uint8_t groupno; /* 6: Bits 5-7: reserved; Bits 0-6: group number */ + uint8_t xfrlen[2]; /* 7-8: Transfer length (in contiguous logical blocks) */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_READ10_SIZEOF 10 + +struct scsicmd_write10_s +{ + uint8_t opcode; /* 0: 0x2a */ + uint8_t flags; /* 1: See SCSICMD_WRITE10FLAGS_* */ + uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */ + uint8_t groupno; /* 6: Bits 5-7: reserved; Bits 0-6: group number */ + uint8_t xfrlen[2]; /* 7-8: Transfer length (in contiguous logical blocks) */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_WRITE10_SIZEOF 10 + +struct scsicmd_verify10_s +{ + uint8_t opcode; /* 0: 0x2f */ + uint8_t flags; /* 1: See SCSICMD_VERIFY10_* definitions */ + uint8_t lba[4]; /* 2-5: Logical block address (LBA) */ + uint8_t groupno; /* 6: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */ + uint8_t len[2]; /* 7-8: Verification length (in blocks) */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_VERIFY10_SIZEOF 10 + +struct scsicmd_synchronizecache10_s +{ + uint8_t opcode; /* 0: 0x35 */ + uint8_t flags; /* 1: See SCSICMD_SYNCHRONIZECACHE10_* definitions */ + uint8_t lba[4]; /* 2-5: Logical block address (LBA) */ + uint8_t groupno; /* 6: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */ + uint8_t len[2]; /* 7-8: Number of logical blocks */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_SYNCHRONIZECACHE10_SIZEOF 10 + +struct scsicmd_modeselect10_s +{ + uint8_t opcode; /* 0: 0x55 */ + uint8_t flags; /* 1: See SCSICMD_MODESELECT10_FLAGS_* */ + uint8_t reserved[5]; /* 2-6: Reserved */ + uint8_t parmlen[2]; /* 7-8: Parameter list length */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_MODESELECT10_SIZEOF 10 + +struct scsiresp_modeparameterhdr10_s +{ + uint8_t mdlen[2]; /* 0-1: Mode data length */ + uint8_t type; /* 2: Medium type */ + uint8_t param; /* 3: Device-specific parameter */ + uint8_t reserved[2]; /* 4-5: reserved */ + uint8_t bdlen[2]; /* 6-7: Block descriptor length */ +}; +#define SCSIRESP_MODEPARAMETERHDR10_SIZEOF 8 + +struct scsicmd_modesense10_s +{ + uint8_t opcode; /* O: 0x5a */ + uint8_t flags; /* 1: See SCSICMD_MODESENSE10_FLAGS_* */ + uint8_t pcpgcode; /* 2: Bits 6-7: PC, bits 0-5: page code */ + uint8_t subpgcode; /* 3: subpage code */ + uint8_t reserved[3]; /* 4-6: reserved */ + uint8_t alloclen[2]; /* 7-8: Allocation length */ + uint8_t control; /* 9: Control */ +}; +#define SCSICMD_MODESENSE10_SIZEOF 10 + +struct scsicmd_readcapacity16_s +{ + uint8_t opcode; /* 0: 0x9e */ + uint8_t action; /* 1: Bits 5-7: Reserved, Bits 0-4: Service action */ + uint8_t lba[8]; /* 2-9: Logical block address (LBA) */ + uint8_t len[4]; /* 10-13: Allocation length */ + uint8_t reserved; /* 14: Reserved */ + uint8_t control; /* 15: Control */ +}; +#define SCSICMD_READCAPACITY16_SIZEOF 16 + +struct scsicmd_read12_s +{ + uint8_t opcode; /* 0: 0xa8 */ + uint8_t flags; /* 1: See SCSICMD_READ12FLAGS_* */ + uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */ + uint8_t xfrlen[4]; /* 6-9: Transfer length (in contiguous logical blocks) */ + uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: reserved; Bits 0-6: group number */ + uint8_t control; /* 11: Control */ +}; +#define SCSICMD_READ12_SIZEOF 12 + +struct scsicmd_write12_s +{ + uint8_t opcode; /* 0: 0xaa */ + uint8_t flags; /* 1: See SCSICMD_WRITE12FLAGS_* */ + uint8_t lba[4]; /* 2-5: Logical Block Address (LBA) */ + uint8_t xfrlen[4]; /* 6-9: Transfer length (in contiguous logical blocks) */ + uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: reserved; Bits 0-6: group number */ + uint8_t control; /* 11: Control */ +}; +#define SCSICMD_WRITE12_SIZEOF 12 + +struct scsicmd_verify12_s +{ + uint8_t opcode; /* 0: 0xaf */ + uint8_t flags; /* 1: See SCSICMD_VERIFY12_* definitions */ + uint8_t lba[4]; /* 2-5: Logical block address (LBA) */ + uint8_t len[4]; /* 6-9: Verification length */ + uint8_t groupno; /* 10: Bit 7: restricted; Bits 5-6: Reserved, Bits 0-4: Group number */ + uint8_t control; /* 11: Control */ +}; +#define SCSICMD_VERIFY12_SIZEOF 12 + +/**************************************************************************** + * Public Functions Definitions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_SCSI_H */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbd_msc.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbd_msc.c new file mode 100644 index 00000000..57781e4b --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbd_msc.c @@ -0,0 +1,993 @@ +/** + * @file usbd_msc.c + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbd_core.h" +#include "usbd_msc.h" +#include "usb_scsi.h" + +/* max USB packet size */ +#ifndef CONFIG_USB_HS +#define MASS_STORAGE_BULK_EP_MPS 64 +#else +#define MASS_STORAGE_BULK_EP_MPS 512 +#endif + +#define MSD_OUT_EP_IDX 0 +#define MSD_IN_EP_IDX 1 + +/* Describe EndPoints configuration */ +static usbd_endpoint_t mass_ep_data[2]; + +/* MSC Bulk-only Stage */ +enum Stage { + MSC_READ_CBW = 0, /* Command Block Wrapper */ + MSC_DATA_OUT = 1, /* Data Out Phase */ + MSC_DATA_IN = 2, /* Data In Phase */ + MSC_SEND_CSW = 3, /* Command Status Wrapper */ + MSC_WAIT_CSW = 4, /* Command Status Wrapper */ +}; + +/* Device data structure */ +struct usbd_msc_cfg_priv { + /* state of the bulk-only state machine */ + enum Stage stage; + struct CBW cbw; + struct CSW csw; + + uint8_t sKey; /* Sense key */ + uint8_t ASC; /* Additional Sense Code */ + uint8_t ASQ; /* Additional Sense Qualifier */ + uint8_t max_lun; + uint16_t scsi_blk_size; + uint32_t scsi_blk_nbr; + + uint32_t scsi_blk_addr; + uint32_t scsi_blk_len; + uint8_t *block_buffer; + +} usbd_msc_cfg; + +/*memory OK (after a usbd_msc_memory_verify)*/ +static bool memOK; + +static void usbd_msc_reset(void) +{ + usbd_msc_cfg.stage = MSC_READ_CBW; + usbd_msc_cfg.scsi_blk_addr = 0U; + usbd_msc_cfg.scsi_blk_len = 0U; + usbd_msc_cfg.max_lun = 0; + usbd_msc_cfg.sKey = 0; + usbd_msc_cfg.ASC = 0; + usbd_msc_cfg.ASQ = 0; + + (void)memset((void *)&usbd_msc_cfg.cbw, 0, sizeof(struct CBW)); + (void)memset((void *)&usbd_msc_cfg.csw, 0, sizeof(struct CSW)); + + usbd_msc_get_cap(0, &usbd_msc_cfg.scsi_blk_nbr, &usbd_msc_cfg.scsi_blk_size); + + if (usbd_msc_cfg.block_buffer) { + free(usbd_msc_cfg.block_buffer); + } + usbd_msc_cfg.block_buffer = malloc(usbd_msc_cfg.scsi_blk_size * sizeof(uint8_t)); + memset(usbd_msc_cfg.block_buffer, 0, usbd_msc_cfg.scsi_blk_size * sizeof(uint8_t)); +} + +/** + * @brief Handler called for Class requests not handled by the USB stack. + * + * @param setup Information about the request to execute. + * @param len Size of the buffer. + * @param data Buffer containing the request result. + * + * @return 0 on success, negative errno code on fail. + */ +static int msc_storage_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USB_LOG_DBG("MSC Class request: " + "bRequest 0x%02x\r\n", + setup->bRequest); + + switch (setup->bRequest) { + case MSC_REQUEST_RESET: + USB_LOG_DBG("MSC_REQUEST_RESET\r\n"); + + if (setup->wLength) { + USB_LOG_WRN("Invalid length\r\n"); + return -1; + } + + usbd_msc_reset(); + break; + + case MSC_REQUEST_GET_MAX_LUN: + USB_LOG_DBG("MSC_REQUEST_GET_MAX_LUN\r\n"); + + if (setup->wLength != 1) { + USB_LOG_WRN("Invalid length\r\n"); + return -1; + } + + *data = (uint8_t *)(&usbd_msc_cfg.max_lun); + *len = 1; + break; + + default: + USB_LOG_WRN("Unhandled MSC Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + + return 0; +} + +static void usbd_msc_bot_abort(void) +{ + if ((usbd_msc_cfg.cbw.bmFlags == 0) && (usbd_msc_cfg.cbw.dDataLength != 0)) { + usbd_ep_set_stall(mass_ep_data[MSD_OUT_EP_IDX].ep_addr); + } + usbd_ep_set_stall(mass_ep_data[MSD_IN_EP_IDX].ep_addr); +} + +static void sendCSW(uint8_t CSW_Status) +{ + usbd_msc_cfg.csw.dSignature = MSC_CSW_Signature; + usbd_msc_cfg.csw.bStatus = CSW_Status; + + /* updating the State Machine , so that we wait CSW when this + * transfer is complete, ie when we get a bulk in callback + */ + usbd_msc_cfg.stage = MSC_WAIT_CSW; + + if (usbd_ep_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.csw, + sizeof(struct CSW), NULL) != 0) { + USB_LOG_ERR("usb write failure\r\n"); + } +} + +static void sendLastData(uint8_t *buffer, uint8_t size) +{ + size = MIN(size, usbd_msc_cfg.cbw.dDataLength); + + /* updating the State Machine , so that we send CSW when this + * transfer is complete, ie when we get a bulk in callback + */ + usbd_msc_cfg.stage = MSC_SEND_CSW; + + if (usbd_ep_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, buffer, size, NULL) != 0) { + USB_LOG_ERR("USB write failed\r\n"); + } + + usbd_msc_cfg.csw.dDataResidue -= size; + usbd_msc_cfg.csw.bStatus = CSW_STATUS_CMD_PASSED; +} + +/** + * @brief SCSI COMMAND + */ +static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len); +static bool SCSI_requestSense(uint8_t **data, uint32_t *len); +static bool SCSI_inquiry(uint8_t **data, uint32_t *len); +static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len); +static bool SCSI_preventAllowMediaRemoval(uint8_t **data, uint32_t *len); +static bool SCSI_modeSense6(uint8_t **data, uint32_t *len); +static bool SCSI_modeSense10(uint8_t **data, uint32_t *len); +static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len); +static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len); +static bool SCSI_read10(uint8_t **data, uint32_t *len); +static bool SCSI_read12(uint8_t **data, uint32_t *len); +static bool SCSI_write10(uint8_t **data, uint32_t *len); +static bool SCSI_write12(uint8_t **data, uint32_t *len); +static bool SCSI_verify10(uint8_t **data, uint32_t *len); + +/** +* @brief SCSI_SetSenseData +* Load the last error code in the error list +* @param sKey: Sense Key +* @param ASC: Additional Sense Code +* @retval none + +*/ +static void SCSI_SetSenseData(uint32_t KCQ) +{ + usbd_msc_cfg.sKey = (uint8_t)(KCQ >> 16); + usbd_msc_cfg.ASC = (uint8_t)(KCQ >> 8); + usbd_msc_cfg.ASQ = (uint8_t)(KCQ); +} + +static bool SCSI_processRead(void) +{ + uint32_t transfer_len; + + USB_LOG_DBG("read addr:%d\r\n", usbd_msc_cfg.scsi_blk_addr); + + transfer_len = MIN(usbd_msc_cfg.scsi_blk_len, MASS_STORAGE_BULK_EP_MPS); + + /* we read an entire block */ + if (!(usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size)) { + if (usbd_msc_sector_read((usbd_msc_cfg.scsi_blk_addr / usbd_msc_cfg.scsi_blk_size), usbd_msc_cfg.block_buffer, usbd_msc_cfg.scsi_blk_size) != 0) { + SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA); + return false; + } + } + + usbd_ep_write(mass_ep_data[MSD_IN_EP_IDX].ep_addr, + &usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], transfer_len, NULL); + + usbd_msc_cfg.scsi_blk_addr += transfer_len; + usbd_msc_cfg.scsi_blk_len -= transfer_len; + usbd_msc_cfg.csw.dDataResidue -= transfer_len; + + if (usbd_msc_cfg.scsi_blk_len == 0) { + usbd_msc_cfg.stage = MSC_SEND_CSW; + } + + return true; +} + +static bool SCSI_processWrite() +{ + uint32_t bytes_read; + USB_LOG_DBG("write addr:%d\r\n", usbd_msc_cfg.scsi_blk_addr); + + /* we fill an array in RAM of 1 block before writing it in memory */ + usbd_ep_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, &usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size], MASS_STORAGE_BULK_EP_MPS, + &bytes_read); + + /* if the array is filled, write it in memory */ + if ((usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size) + bytes_read >= usbd_msc_cfg.scsi_blk_size) { + if (usbd_msc_sector_write((usbd_msc_cfg.scsi_blk_addr / usbd_msc_cfg.scsi_blk_size), usbd_msc_cfg.block_buffer, usbd_msc_cfg.scsi_blk_size) != 0) { + SCSI_SetSenseData(SCSI_KCQHE_WRITEFAULT); + return false; + } + } + + usbd_msc_cfg.scsi_blk_addr += bytes_read; + usbd_msc_cfg.scsi_blk_len -= bytes_read; + usbd_msc_cfg.csw.dDataResidue -= bytes_read; + + if (usbd_msc_cfg.scsi_blk_len == 0) { + sendCSW(CSW_STATUS_CMD_PASSED); + } + + return true; +} + +static bool SCSI_processVerify() +{ +#if 0 + uint32_t bytes_read; + uint8_t out_buffer[MASS_STORAGE_BULK_EP_MPS]; + + USB_LOG_DBG("verify addr:%d\r\n", usbd_msc_cfg.scsi_blk_addr); + + /* we fill an array in RAM of 1 block before writing it in memory */ + usbd_ep_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, out_buffer, MASS_STORAGE_BULK_EP_MPS, + &bytes_read); + + /* we read an entire block */ + if (!(usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size)) { + if (usbd_msc_sector_read((usbd_msc_cfg.scsi_blk_addr / usbd_msc_cfg.scsi_blk_size), usbd_msc_cfg.block_buffer, usbd_msc_cfg.scsi_blk_size) != 0) { + SCSI_SetSenseData(SCSI_KCQHE_UREINRESERVEDAREA); + return false; + } + } + + /* info are in RAM -> no need to re-read memory */ + for (uint16_t i = 0U; i < bytes_read; i++) { + if (usbd_msc_cfg.block_buffer[usbd_msc_cfg.scsi_blk_addr % usbd_msc_cfg.scsi_blk_size + i] != out_buffer[i]) { + USB_LOG_DBG("Mismatch sector %d offset %d", + usbd_msc_cfg.scsi_blk_addr / usbd_msc_cfg.scsi_blk_size, i); + memOK = false; + break; + } + } + + usbd_msc_cfg.scsi_blk_addr += bytes_read; + usbd_msc_cfg.scsi_blk_len -= bytes_read; + usbd_msc_cfg.csw.dDataResidue -= bytes_read; + + if (usbd_msc_cfg.scsi_blk_len == 0) { + sendCSW(CSW_STATUS_CMD_PASSED); + } +#endif + return true; +} + +static bool SCSI_CBWDecode() +{ + uint8_t *buf2send = usbd_msc_cfg.block_buffer; + uint32_t len2send = 0; + uint32_t bytes_read; + bool ret = false; + + usbd_ep_read(mass_ep_data[MSD_OUT_EP_IDX].ep_addr, (uint8_t *)&usbd_msc_cfg.cbw, USB_SIZEOF_MSC_CBW, + &bytes_read); + + if (bytes_read != sizeof(struct CBW)) { + USB_LOG_ERR("size != sizeof(cbw)\r\n"); + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + usbd_msc_cfg.csw.dTag = usbd_msc_cfg.cbw.dTag; + usbd_msc_cfg.csw.dDataResidue = usbd_msc_cfg.cbw.dDataLength; + + if ((usbd_msc_cfg.cbw.bLUN > 1) || (usbd_msc_cfg.cbw.dSignature != MSC_CBW_Signature) || (usbd_msc_cfg.cbw.bCBLength < 1) || (usbd_msc_cfg.cbw.bCBLength > 16)) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } else { + switch (usbd_msc_cfg.cbw.CB[0]) { + case SCSI_CMD_TESTUNITREADY: + ret = SCSI_testUnitReady(&buf2send, &len2send); + break; + case SCSI_CMD_REQUESTSENSE: + ret = SCSI_requestSense(&buf2send, &len2send); + break; + case SCSI_CMD_INQUIRY: + ret = SCSI_inquiry(&buf2send, &len2send); + break; + case SCSI_CMD_STARTSTOPUNIT: + ret = SCSI_startStopUnit(&buf2send, &len2send); + break; + case SCSI_CMD_PREVENTMEDIAREMOVAL: + ret = SCSI_preventAllowMediaRemoval(&buf2send, &len2send); + break; + case SCSI_CMD_MODESENSE6: + ret = SCSI_modeSense6(&buf2send, &len2send); + break; + case SCSI_CMD_MODESENSE10: + ret = SCSI_modeSense10(&buf2send, &len2send); + break; + case SCSI_CMD_READFORMATCAPACITIES: + ret = SCSI_readFormatCapacity(&buf2send, &len2send); + break; + case SCSI_CMD_READCAPACITY10: + ret = SCSI_readCapacity10(&buf2send, &len2send); + break; + case SCSI_CMD_READ10: + ret = SCSI_read10(NULL, 0); + break; + case SCSI_CMD_READ12: + ret = SCSI_read12(NULL, 0); + break; + case SCSI_CMD_WRITE10: + ret = SCSI_write10(NULL, 0); + break; + case SCSI_CMD_WRITE12: + ret = SCSI_write12(NULL, 0); + break; + case SCSI_CMD_VERIFY10: + ret = SCSI_verify10(NULL, 0); + break; + + default: + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + USB_LOG_WRN("unsupported cmd:0x%02x\r\n", usbd_msc_cfg.cbw.CB[0]); + ret = false; + break; + } + } + if (ret) { + if (usbd_msc_cfg.stage == MSC_READ_CBW) { + if (len2send) { + sendLastData(buf2send, len2send); + } else { + sendCSW(CSW_STATUS_CMD_PASSED); + } + } + } + return ret; +} + +static bool SCSI_testUnitReady(uint8_t **data, uint32_t *len) +{ + if (usbd_msc_cfg.cbw.dDataLength != 0U) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + *data = NULL; + *len = 0; + return true; +} + +static bool SCSI_requestSense(uint8_t **data, uint32_t *len) +{ + uint8_t data_len = SCSIRESP_FIXEDSENSEDATA_SIZEOF; + if (usbd_msc_cfg.cbw.dDataLength == 0U) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_FIXEDSENSEDATA_SIZEOF) { + data_len = usbd_msc_cfg.cbw.CB[4]; + } + + uint8_t request_sense[SCSIRESP_FIXEDSENSEDATA_SIZEOF] = { + 0x70, + 0x00, + 0x00, /* Sense Key */ + 0x00, + 0x00, + 0x00, + 0x00, + SCSIRESP_FIXEDSENSEDATA_SIZEOF - 8, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, /* Additional Sense Code */ + 0x00, /* Additional Sense Request */ + 0x00, + 0x00, + 0x00, + 0x00, + }; + + request_sense[2] = usbd_msc_cfg.sKey; + request_sense[12] = usbd_msc_cfg.ASC; + request_sense[13] = usbd_msc_cfg.ASQ; +#if 0 + request_sense[ 2] = 0x06; /* UNIT ATTENTION */ + request_sense[12] = 0x28; /* Additional Sense Code: Not ready to ready transition */ + request_sense[13] = 0x00; /* Additional Sense Code Qualifier */ +#endif +#if 0 + request_sense[ 2] = 0x02; /* NOT READY */ + request_sense[12] = 0x3A; /* Additional Sense Code: Medium not present */ + request_sense[13] = 0x00; /* Additional Sense Code Qualifier */ +#endif +#if 0 + request_sense[ 2] = 0x05; /* ILLEGAL REQUEST */ + request_sense[12] = 0x20; /* Additional Sense Code: Invalid command */ + request_sense[13] = 0x00; /* Additional Sense Code Qualifier */ +#endif +#if 0 + request_sense[ 2] = 0x00; /* NO SENSE */ + request_sense[12] = 0x00; /* Additional Sense Code: No additional code */ + request_sense[13] = 0x00; /* Additional Sense Code Qualifier */ +#endif + + memcpy(*data, (uint8_t *)request_sense, data_len); + *len = data_len; + return true; +} + +static bool SCSI_inquiry(uint8_t **data, uint32_t *len) +{ + uint8_t data_len = SCSIRESP_INQUIRY_SIZEOF; + + uint8_t inquiry00[6] = { + 0x00, + 0x00, + 0x00, + (0x06 - 4U), + 0x00, + 0x80 + }; + + /* USB Mass storage VPD Page 0x80 Inquiry Data for Unit Serial Number */ + uint8_t inquiry80[8] = { + 0x00, + 0x80, + 0x00, + 0x08, + 0x20, /* Put Product Serial number */ + 0x20, + 0x20, + 0x20 + }; + + uint8_t inquiry[SCSIRESP_INQUIRY_SIZEOF] = { + /* 36 */ + + /* LUN 0 */ + 0x00, + 0x80, + 0x02, + 0x02, + (SCSIRESP_INQUIRY_SIZEOF - 5), + 0x00, + 0x00, + 0x00, + 'B', 'o', 'u', 'f', 'f', 'a', 'l', 'o', /* Manufacturer : 8 bytes */ + 'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */ + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + '0', '.', '0', '1' /* Version : 4 Bytes */ + }; + + if (usbd_msc_cfg.cbw.dDataLength == 0U) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + if ((usbd_msc_cfg.cbw.CB[1] & 0x01U) != 0U) { /* Evpd is set */ + if (usbd_msc_cfg.cbw.CB[2] == 0U) { /* Request for Supported Vital Product Data Pages*/ + data_len = 0x06; + memcpy(*data, (uint8_t *)inquiry00, data_len); + } else if (usbd_msc_cfg.cbw.CB[2] == 0x80U) { /* Request for VPD page 0x80 Unit Serial Number */ + data_len = 0x08; + memcpy(*data, (uint8_t *)inquiry80, data_len); + } else { /* Request Not supported */ + SCSI_SetSenseData(SCSI_KCQIR_INVALIDFIELDINCBA); + return false; + } + } else { + if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_INQUIRY_SIZEOF) { + data_len = usbd_msc_cfg.cbw.CB[4]; + } + memcpy(*data, (uint8_t *)inquiry, data_len); + } + + *len = data_len; + return true; +} + +static bool SCSI_startStopUnit(uint8_t **data, uint32_t *len) +{ + if (usbd_msc_cfg.cbw.dDataLength != 0U) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x1U) /* START=1 */ + { + //SCSI_MEDIUM_UNLOCKED; + } else if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x2U) /* START=0 and LOEJ Load Eject=1 */ + { + //SCSI_MEDIUM_EJECTED; + } else if ((usbd_msc_cfg.cbw.CB[4] & 0x3U) == 0x3U) /* START=1 and LOEJ Load Eject=1 */ + { + //SCSI_MEDIUM_UNLOCKED; + } else { + } + + *data = NULL; + *len = 0; + return true; +} + +static bool SCSI_preventAllowMediaRemoval(uint8_t **data, uint32_t *len) +{ + if (usbd_msc_cfg.cbw.dDataLength != 0U) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + if (usbd_msc_cfg.cbw.CB[4] == 0U) { + //SCSI_MEDIUM_UNLOCKED; + } else { + //SCSI_MEDIUM_LOCKED; + } + *data = NULL; + *len = 0; + return true; +} + +static bool SCSI_modeSense6(uint8_t **data, uint32_t *len) +{ + uint8_t data_len = 4; + if (usbd_msc_cfg.cbw.dDataLength == 0U) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + if (usbd_msc_cfg.cbw.CB[4] < SCSIRESP_MODEPARAMETERHDR6_SIZEOF) { + data_len = usbd_msc_cfg.cbw.CB[4]; + } + + uint8_t sense6[SCSIRESP_MODEPARAMETERHDR6_SIZEOF] = { 0x03, 0x00, 0x00, 0x00 }; + + memcpy(*data, (uint8_t *)sense6, data_len); + *len = data_len; + return true; +} + +static bool SCSI_modeSense10(uint8_t **data, uint32_t *len) +{ + uint8_t data_len = 27; + if (usbd_msc_cfg.cbw.dDataLength == 0U) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + if (usbd_msc_cfg.cbw.CB[8] < 27) { + data_len = usbd_msc_cfg.cbw.CB[8]; + } + + uint8_t sense10[27] = { + 0x00, + 0x26, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x08, + 0x12, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + }; + + memcpy(*data, (uint8_t *)sense10, data_len); + *len = data_len; + return true; +} + +static bool SCSI_readFormatCapacity(uint8_t **data, uint32_t *len) +{ + if (usbd_msc_cfg.cbw.dDataLength == 0U) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + uint8_t format_capacity[SCSIRESP_READFORMATCAPACITIES_SIZEOF] = { + 0x00, + 0x00, + 0x00, + 0x08, /* Capacity List Length */ + (uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 24) & 0xff), + (uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 16) & 0xff), + (uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 8) & 0xff), + (uint8_t)((usbd_msc_cfg.scsi_blk_nbr >> 0) & 0xff), + + 0x02, /* Descriptor Code: Formatted Media */ + 0x00, + (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 8) & 0xff), + (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 0) & 0xff), + }; + + memcpy(*data, (uint8_t *)format_capacity, SCSIRESP_READFORMATCAPACITIES_SIZEOF); + *len = SCSIRESP_READFORMATCAPACITIES_SIZEOF; + return true; +} + +static bool SCSI_readCapacity10(uint8_t **data, uint32_t *len) +{ + if (usbd_msc_cfg.cbw.dDataLength == 0U) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + uint8_t capacity10[SCSIRESP_READCAPACITY10_SIZEOF] = { + (uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 24) & 0xff), + (uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 16) & 0xff), + (uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 8) & 0xff), + (uint8_t)(((usbd_msc_cfg.scsi_blk_nbr - 1) >> 0) & 0xff), + + (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 24) & 0xff), + (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 16) & 0xff), + (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 8) & 0xff), + (uint8_t)((usbd_msc_cfg.scsi_blk_size >> 0) & 0xff), + }; + + memcpy(*data, (uint8_t *)&capacity10, SCSIRESP_READCAPACITY10_SIZEOF); + *len = SCSIRESP_READCAPACITY10_SIZEOF; + return true; +} + +static bool SCSI_read10(uint8_t **data, uint32_t *len) +{ + /* Logical Block Address of First Block */ + uint32_t lba = 0; + uint32_t blk_num = 0; + if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x80U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + lba = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); + USB_LOG_DBG("lba: 0x%x\r\n", lba); + + usbd_msc_cfg.scsi_blk_addr = lba * usbd_msc_cfg.scsi_blk_size; + + /* Number of Blocks to transfer */ + blk_num = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); + + usbd_msc_cfg.scsi_blk_len = blk_num * usbd_msc_cfg.scsi_blk_size; + + if ((lba + blk_num) > usbd_msc_cfg.scsi_blk_nbr) { + SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE); + USB_LOG_ERR("LBA out of range\r\n"); + return false; + } + + if (usbd_msc_cfg.cbw.dDataLength != usbd_msc_cfg.scsi_blk_len) { + USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n"); + return false; + } + usbd_msc_cfg.stage = MSC_DATA_IN; + return SCSI_processRead(); +} + +static bool SCSI_read12(uint8_t **data, uint32_t *len) +{ + /* Logical Block Address of First Block */ + uint32_t lba = 0; + uint32_t blk_num = 0; + if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x80U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + lba = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); + USB_LOG_DBG("lba: 0x%x\r\n", lba); + + usbd_msc_cfg.scsi_blk_addr = lba * usbd_msc_cfg.scsi_blk_size; + + /* Number of Blocks to transfer */ + blk_num = GET_BE32(&usbd_msc_cfg.cbw.CB[6]); + + USB_LOG_DBG("num (block) : 0x%x\r\n", blk_num); + usbd_msc_cfg.scsi_blk_len = blk_num * usbd_msc_cfg.scsi_blk_size; + + if ((lba + blk_num) > usbd_msc_cfg.scsi_blk_nbr) { + SCSI_SetSenseData(SCSI_KCQIR_LBAOUTOFRANGE); + USB_LOG_ERR("LBA out of range\r\n"); + return false; + } + + if (usbd_msc_cfg.cbw.dDataLength != usbd_msc_cfg.scsi_blk_len) { + USB_LOG_ERR("scsi_blk_len does not match with dDataLength\r\n"); + return false; + } + usbd_msc_cfg.stage = MSC_DATA_IN; + return SCSI_processRead(); +} + +static bool SCSI_write10(uint8_t **data, uint32_t *len) +{ + /* Logical Block Address of First Block */ + uint32_t lba = 0; + uint32_t blk_num = 0; + if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + lba = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); + USB_LOG_DBG("lba: 0x%x\r\n", lba); + + usbd_msc_cfg.scsi_blk_addr = lba * usbd_msc_cfg.scsi_blk_size; + + /* Number of Blocks to transfer */ + blk_num = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); + + USB_LOG_DBG("num (block) : 0x%x\r\n", blk_num); + usbd_msc_cfg.scsi_blk_len = blk_num * usbd_msc_cfg.scsi_blk_size; + + if ((lba + blk_num) > usbd_msc_cfg.scsi_blk_nbr) { + USB_LOG_ERR("LBA out of range\r\n"); + return false; + } + + if (usbd_msc_cfg.cbw.dDataLength != usbd_msc_cfg.scsi_blk_len) { + return false; + } + usbd_msc_cfg.stage = MSC_DATA_OUT; + return true; +} + +static bool SCSI_write12(uint8_t **data, uint32_t *len) +{ + /* Logical Block Address of First Block */ + uint32_t lba = 0; + uint32_t blk_num = 0; + if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + lba = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); + USB_LOG_DBG("lba: 0x%x\r\n", lba); + + usbd_msc_cfg.scsi_blk_addr = lba * usbd_msc_cfg.scsi_blk_size; + + /* Number of Blocks to transfer */ + blk_num = GET_BE32(&usbd_msc_cfg.cbw.CB[6]); + + USB_LOG_DBG("num (block) : 0x%x\r\n", blk_num); + usbd_msc_cfg.scsi_blk_len = blk_num * usbd_msc_cfg.scsi_blk_size; + + if ((lba + blk_num) > usbd_msc_cfg.scsi_blk_nbr) { + USB_LOG_ERR("LBA out of range\r\n"); + return false; + } + + if (usbd_msc_cfg.cbw.dDataLength != usbd_msc_cfg.scsi_blk_len) { + return false; + } + usbd_msc_cfg.stage = MSC_DATA_OUT; + return true; +} + +static bool SCSI_verify10(uint8_t **data, uint32_t *len) +{ + /* Logical Block Address of First Block */ + uint32_t lba = 0; + uint32_t blk_num = 0; + + if ((usbd_msc_cfg.cbw.CB[1] & 0x02U) == 0x00U) { + return true; + } + + if (((usbd_msc_cfg.cbw.bmFlags & 0x80U) != 0x00U) || (usbd_msc_cfg.cbw.dDataLength == 0U)) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDCOMMAND); + return false; + } + + if ((usbd_msc_cfg.cbw.CB[1] & 0x02U) == 0x02U) { + SCSI_SetSenseData(SCSI_KCQIR_INVALIDFIELDINCBA); + return false; /* Error, Verify Mode Not supported*/ + } + + lba = GET_BE32(&usbd_msc_cfg.cbw.CB[2]); + USB_LOG_DBG("lba: 0x%x\r\n", lba); + + usbd_msc_cfg.scsi_blk_addr = lba * usbd_msc_cfg.scsi_blk_size; + + /* Number of Blocks to transfer */ + blk_num = GET_BE16(&usbd_msc_cfg.cbw.CB[7]); + + USB_LOG_DBG("num (block) : 0x%x\r\n", blk_num); + usbd_msc_cfg.scsi_blk_len = blk_num * usbd_msc_cfg.scsi_blk_size; + + if ((lba + blk_num) > usbd_msc_cfg.scsi_blk_nbr) { + USB_LOG_ERR("LBA out of range\r\n"); + return false; + } + + if (usbd_msc_cfg.cbw.dDataLength != usbd_msc_cfg.scsi_blk_len) { + return false; + } + + memOK = true; + usbd_msc_cfg.stage = MSC_DATA_OUT; + return true; +} + +static void mass_storage_bulk_out(uint8_t ep) +{ + switch (usbd_msc_cfg.stage) { + case MSC_READ_CBW: + if (SCSI_CBWDecode() == false) { + USB_LOG_ERR("Command:0x%02x decode err\r\n", usbd_msc_cfg.cbw.CB[0]); + usbd_msc_bot_abort(); + return; + } + break; + /* last command is write10 or write12,and has caculated blk_addr and blk_len,so the device start reading data from host*/ + case MSC_DATA_OUT: + switch (usbd_msc_cfg.cbw.CB[0]) { + case SCSI_CMD_WRITE10: + case SCSI_CMD_WRITE12: + if (SCSI_processWrite() == false) { + sendCSW(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/ + //return; + } + break; + case SCSI_CMD_VERIFY10: + if (SCSI_processVerify() == false) { + sendCSW(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/ + //return; + } + break; + default: + break; + } + break; + default: + break; + } + + /*set ep ack to recv next data*/ + usbd_ep_read(ep, NULL, 0, NULL); +} + +/** + * @brief EP Bulk IN handler, used to send data to the Host + * + * @param ep Endpoint address. + * @param ep_status Endpoint status code. + * + * @return N/A. + */ +static void mass_storage_bulk_in(uint8_t ep) +{ + switch (usbd_msc_cfg.stage) { + /* last command is read10 or read12,and has caculated blk_addr and blk_len,so the device has to send remain data to host*/ + case MSC_DATA_IN: + switch (usbd_msc_cfg.cbw.CB[0]) { + case SCSI_CMD_READ10: + case SCSI_CMD_READ12: + if (SCSI_processRead() == false) { + sendCSW(CSW_STATUS_CMD_FAILED); /* send fail status to host,and the host will retry*/ + return; + } + break; + default: + break; + } + + break; + + /*the device has to send a CSW*/ + case MSC_SEND_CSW: + sendCSW(CSW_STATUS_CMD_PASSED); + break; + + /*the host has received the CSW*/ + case MSC_WAIT_CSW: + usbd_msc_cfg.stage = MSC_READ_CBW; + break; + + default: + break; + } +} + +void msc_storage_notify_handler(uint8_t event, void *arg) +{ + switch (event) { + case USBD_EVENT_RESET: + usbd_msc_reset(); + break; + + default: + break; + } +} + +static usbd_class_t msc_class; + +static usbd_interface_t msc_intf = { + .class_handler = msc_storage_class_request_handler, + .vendor_handler = NULL, + .notify_handler = msc_storage_notify_handler, +}; + +void usbd_msc_class_init(uint8_t out_ep, uint8_t in_ep) +{ + msc_class.name = "usbd_msc"; + + usbd_class_register(&msc_class); + usbd_class_add_interface(&msc_class, &msc_intf); + + mass_ep_data[0].ep_addr = out_ep; + mass_ep_data[0].ep_cb = mass_storage_bulk_out; + mass_ep_data[1].ep_addr = in_ep; + mass_ep_data[1].ep_cb = mass_storage_bulk_in; + + usbd_interface_add_endpoint(&msc_intf, &mass_ep_data[0]); + usbd_interface_add_endpoint(&msc_intf, &mass_ep_data[1]); +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbd_msc.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbd_msc.h new file mode 100644 index 00000000..ba17e617 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbd_msc.h @@ -0,0 +1,30 @@ +/** + * @file + * @brief USB Mass Storage Class public header + * + * Header follows the Mass Storage Class Specification + * (Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf) and + * Mass Storage Class Bulk-Only Transport Specification + * (usbmassbulk_10.pdf). + * Header is limited to Bulk-Only Transfer protocol. + */ + +#ifndef _USBD_MSC_H__ +#define _USBD_MSC_H__ + +#include "usb_msc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void usbd_msc_class_init(uint8_t out_ep, uint8_t in_ep); +void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size); +int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length); +int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length); + +#ifdef __cplusplus +} +#endif + +#endif /* USBD_MSC_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbh_msc.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbh_msc.c new file mode 100644 index 00000000..a64ca7fa --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbh_msc.c @@ -0,0 +1,439 @@ +/** + * @file usbh_msc.c + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbh_core.h" +#include "usbh_msc.h" +#include "usb_scsi.h" + +#define DEV_FORMAT "/dev/sd%c" +#define DEV_NAMELEN 16 + +static uint32_t g_devinuse = 0; + +/**************************************************************************** + * Name: usbh_msc_devno_alloc + * + * Description: + * Allocate a unique /dev/ttyACM[n] minor number in the range 0-31. + * + ****************************************************************************/ + +static int usbh_msc_devno_alloc(struct usbh_msc *priv) +{ + uint32_t flags; + int devno; + + flags = usb_osal_enter_critical_section(); + for (devno = 0; devno < 26; devno++) { + uint32_t bitno = 1 << devno; + if ((g_devinuse & bitno) == 0) { + g_devinuse |= bitno; + priv->sdchar = 'a' + devno; + usb_osal_leave_critical_section(flags); + return 0; + } + } + + usb_osal_leave_critical_section(flags); + return -EMFILE; +} + +/**************************************************************************** + * Name: usbh_msc_devno_free + * + * Description: + * Free a /dev/sd[n] minor number so that it can be used. + * + ****************************************************************************/ + +static void usbh_msc_devno_free(struct usbh_msc *priv) +{ + int devno = priv->sdchar - 'a'; + + if (devno >= 0 && devno < 26) { + uint32_t flags = usb_osal_enter_critical_section(); + g_devinuse &= ~(1 << devno); + usb_osal_leave_critical_section(flags); + } +} + +/**************************************************************************** + * Name: usbh_msc_mkdevname + * + * Description: + * Format a /dev/sd[n] device name given a minor number. + * + ****************************************************************************/ + +static inline void usbh_msc_mkdevname(struct usbh_msc *priv, char *devname) +{ + snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->sdchar); +} + +static int usbh_msc_get_maxlun(struct usbh_hubport *hport, uint8_t intf, uint8_t *buffer) +{ + struct usb_setup_packet *setup; + struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv; + + setup = msc_class->setup; + + if (msc_class->intf != intf) { + return -1; + } + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_INTERFACE; + setup->bRequest = MSC_REQUEST_GET_MAX_LUN; + setup->wValue = 0; + setup->wIndex = intf; + setup->wLength = 1; + + return usbh_control_transfer(hport->ep0, setup, buffer); +} + +static void usbh_msc_cbw_dump(struct CBW *cbw) +{ + int i; + + USB_LOG_INFO("CBW:\r\n"); + USB_LOG_INFO(" signature: 0x%08x\r\n", (unsigned int)cbw->dSignature); + USB_LOG_INFO(" tag: 0x%08x\r\n", (unsigned int)cbw->dTag); + USB_LOG_INFO(" datlen: 0x%08x\r\n", (unsigned int)cbw->dDataLength); + USB_LOG_INFO(" flags: 0x%02x\r\n", cbw->bmFlags); + USB_LOG_INFO(" lun: 0x%02x\r\n", cbw->bLUN); + USB_LOG_INFO(" cblen: 0x%02x\r\n", cbw->bCBLength); + + USB_LOG_INFO("CB:\r\n"); + for (i = 0; i < cbw->bCBLength; i += 8) { + USB_LOG_INFO(" 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\r\n", + cbw->CB[i], cbw->CB[i + 1], cbw->CB[i + 2], + cbw->CB[i + 3], cbw->CB[i + 4], cbw->CB[i + 5], + cbw->CB[i + 6], cbw->CB[i + 7]); + } +} + +static void usbh_msc_csw_dump(struct CSW *csw) +{ + USB_LOG_INFO("CSW:\r\n"); + USB_LOG_INFO(" signature: 0x%08x\r\n", (unsigned int)csw->dSignature); + USB_LOG_INFO(" tag: 0x%08x\r\n", (unsigned int)csw->dTag); + USB_LOG_INFO(" residue: 0x%08x\r\n", (unsigned int)csw->dDataResidue); + USB_LOG_INFO(" status: 0x%02x\r\n", csw->bStatus); +} + +static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class) +{ + int nbytes; + struct CBW *cbw; + + /* Construct the CBW */ + cbw = (struct CBW *)msc_class->tx_buffer; + memset(cbw, 0, USB_SIZEOF_MSC_CBW); + cbw->dSignature = MSC_CBW_Signature; + + cbw->bCBLength = SCSICMD_TESTUNITREADY_SIZEOF; + cbw->CB[0] = SCSI_CMD_TESTUNITREADY; + + /* Send the CBW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + if (nbytes >= 0) { + /* Receive the CSW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + if (nbytes >= 0) { + usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + } + } + return nbytes < 0 ? (int)nbytes : 0; +} + +static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class) +{ + int nbytes; + struct CBW *cbw; + + /* Construct the CBW */ + cbw = (struct CBW *)msc_class->tx_buffer; + memset(cbw, 0, USB_SIZEOF_MSC_CBW); + cbw->dSignature = MSC_CBW_Signature; + + cbw->bmFlags = 0x80; + cbw->bCBLength = SCSIRESP_FIXEDSENSEDATA_SIZEOF; + cbw->dDataLength = SCSICMD_REQUESTSENSE_SIZEOF; + cbw->CB[0] = SCSI_CMD_REQUESTSENSE; + cbw->CB[4] = SCSIRESP_FIXEDSENSEDATA_SIZEOF; + /* Send the CBW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + if (nbytes >= 0) { + /* Receive the sense data response */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF); + if (nbytes >= 0) { + /* Receive the CSW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + if (nbytes >= 0) { + usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + } + } + } + return nbytes < 0 ? (int)nbytes : 0; +} + +static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class) +{ + int nbytes; + struct CBW *cbw; + + /* Construct the CBW */ + cbw = (struct CBW *)msc_class->tx_buffer; + memset(cbw, 0, USB_SIZEOF_MSC_CBW); + cbw->dSignature = MSC_CBW_Signature; + + cbw->dDataLength = SCSIRESP_INQUIRY_SIZEOF; + cbw->bmFlags = 0x80; + cbw->bCBLength = SCSICMD_INQUIRY_SIZEOF; + cbw->CB[0] = SCSI_CMD_INQUIRY; + cbw->CB[4] = SCSIRESP_INQUIRY_SIZEOF; + + /* Send the CBW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + if (nbytes >= 0) { + /* Receive the sense data response */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_INQUIRY_SIZEOF); + if (nbytes >= 0) { + /* Receive the CSW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + if (nbytes >= 0) { + usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + } + } + } + return nbytes < 0 ? (int)nbytes : 0; +} + +static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class) +{ + int nbytes; + struct CBW *cbw; + + /* Construct the CBW */ + cbw = (struct CBW *)msc_class->tx_buffer; + memset(cbw, 0, USB_SIZEOF_MSC_CBW); + cbw->dSignature = MSC_CBW_Signature; + + cbw->dDataLength = SCSIRESP_READCAPACITY10_SIZEOF; + cbw->bmFlags = 0x80; + cbw->bCBLength = SCSICMD_READCAPACITY10_SIZEOF; + cbw->CB[0] = SCSI_CMD_READCAPACITY10; + + /* Send the CBW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + if (nbytes >= 0) { + /* Receive the sense data response */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_READCAPACITY10_SIZEOF); + if (nbytes >= 0) { + /* Save the capacity information */ + msc_class->blocknum = GET_BE32(&msc_class->tx_buffer[0]) + 1; + msc_class->blocksize = GET_BE32(&msc_class->tx_buffer[4]); + USB_LOG_INFO("capacity info:\r\n"); + USB_LOG_INFO("block num:%d,block size:%d\r\n", (unsigned int)msc_class->blocknum, (unsigned int)msc_class->blocksize); + /* Receive the CSW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + if (nbytes >= 0) { + usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + } + } + } + return nbytes < 0 ? (int)nbytes : 0; +} + +int usbh_msc_mem_write(struct usbh_msc *msc_class, uint32_t sector, const uint8_t *buffer, uint32_t nsectors) +{ + int nbytes; + struct CBW *cbw; + + /* Construct the CBW */ + cbw = (struct CBW *)msc_class->tx_buffer; + memset(cbw, 0, USB_SIZEOF_MSC_CBW); + cbw->dSignature = MSC_CBW_Signature; + + cbw->dDataLength = (msc_class->blocksize * nsectors); + cbw->bCBLength = SCSICMD_WRITE10_SIZEOF; + cbw->CB[0] = SCSI_CMD_WRITE10; + + SET_BE24(&cbw->CB[2], sector); + SET_BE24(&cbw->CB[7], nsectors); + + /* Send the CBW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + if (nbytes >= 0) { + /* Send the user data */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)buffer, msc_class->blocksize * nsectors); + if (nbytes >= 0) { + /* Receive the CSW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + if (nbytes >= 0) { + usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + } + } + } + return nbytes < 0 ? (int)nbytes : 0; +} + +int usbh_msc_mem_read(struct usbh_msc *msc_class, uint32_t sector, const uint8_t *buffer, uint32_t nsectors) +{ + int nbytes; + struct CBW *cbw; + + /* Construct the CBW */ + cbw = (struct CBW *)msc_class->tx_buffer; + memset(cbw, 0, USB_SIZEOF_MSC_CBW); + cbw->dSignature = MSC_CBW_Signature; + + cbw->dDataLength = (msc_class->blocksize * nsectors); + cbw->bmFlags = 0x80; + cbw->bCBLength = SCSICMD_READ10_SIZEOF; + cbw->CB[0] = SCSI_CMD_READ10; + + SET_BE24(&cbw->CB[2], sector); + SET_BE24(&cbw->CB[7], nsectors); + + /* Send the CBW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + if (nbytes >= 0) { + /* Receive the user data */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, (uint8_t *)buffer, msc_class->blocksize * nsectors); + if (nbytes >= 0) { + /* Receive the CSW */ + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + if (nbytes >= 0) { + usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); + } + } + } + return nbytes < 0 ? (int)nbytes : 0; +} + +int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf) +{ + struct usbh_endpoint_cfg ep_cfg = { 0 }; + struct usb_endpoint_descriptor *ep_desc; + + char devname[DEV_NAMELEN]; + int ret; + + struct usbh_msc *msc_class = usb_malloc(sizeof(struct usbh_msc)); + if (msc_class == NULL) { + USB_LOG_ERR("Fail to alloc msc_class\r\n"); + return -ENOMEM; + } + + memset(msc_class, 0, sizeof(struct usbh_msc)); + + usbh_msc_devno_alloc(msc_class); + usbh_msc_mkdevname(msc_class, devname); + + hport->config.intf[intf].priv = msc_class; + + msc_class->setup = usb_iomalloc(sizeof(struct usb_setup_packet)); + if (msc_class->setup == NULL) { + USB_LOG_ERR("Fail to alloc setup\r\n"); + return -ENOMEM; + } + msc_class->tx_buffer = usb_iomalloc(128); + if (msc_class->tx_buffer == NULL) { + USB_LOG_ERR("Fail to alloc tx_buffer\r\n"); + return -ENOMEM; + } + ret = usbh_msc_get_maxlun(hport, intf, msc_class->tx_buffer); + if (ret < 0) { + return ret; + } + + USB_LOG_INFO("Get max LUN:%u\r\n", msc_class->tx_buffer[0]); + + for (uint8_t i = 0; i < hport->config.intf[intf].intf_desc.bNumEndpoints; i++) { + ep_desc = &hport->config.intf[intf].ep[i].ep_desc; + + ep_cfg.ep_addr = ep_desc->bEndpointAddress; + ep_cfg.ep_type = ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_interval = ep_desc->bInterval; + ep_cfg.hport = hport; + if (ep_desc->bEndpointAddress & 0x80) { + usbh_ep_alloc(&msc_class->bulkin, &ep_cfg); + } else { + usbh_ep_alloc(&msc_class->bulkout, &ep_cfg); + } + } + + USB_LOG_INFO("Register MSC Class:%s\r\n", devname); + + ret = usbh_msc_scsi_testunitready(msc_class); + ret = usbh_msc_scsi_inquiry(msc_class); + ret = usbh_msc_scsi_readcapacity10(msc_class); + + return ret; +} + +int usbh_msc_disconnect(struct usbh_hubport *hport, uint8_t intf) +{ + char devname[DEV_NAMELEN]; + int ret = 0; + + struct usbh_msc *msc_class = (struct usbh_msc *)hport->config.intf[intf].priv; + + if (msc_class) { + usbh_msc_devno_free(msc_class); + usbh_msc_mkdevname(msc_class, devname); + + if (msc_class->bulkin) { + ret = usb_ep_cancel(msc_class->bulkin); + if (ret < 0) { + } + usbh_ep_free(msc_class->bulkin); + } + + if (msc_class->bulkout) { + ret = usb_ep_cancel(msc_class->bulkout); + if (ret < 0) { + } + usbh_ep_free(msc_class->bulkout); + } + + if (msc_class->setup) + usb_iofree(msc_class->setup); + if (msc_class->tx_buffer) + usb_iofree(msc_class->tx_buffer); + + usb_free(msc_class); + + hport->config.intf[intf].priv = NULL; + + USB_LOG_INFO("Unregister MSC Class:%s\r\n", devname); + } + + return ret; +} + +const struct usbh_class_driver msc_class_driver = { + .driver_name = "msc", + .connect = usbh_msc_connect, + .disconnect = usbh_msc_disconnect +}; \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbh_msc.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbh_msc.h new file mode 100644 index 00000000..7318028a --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/msc/usbh_msc.h @@ -0,0 +1,49 @@ +/** + * @file usbh_msc.h + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBH_MSC_H +#define _USBH_MSC_H + +#include "usb_msc.h" +#include "usb_scsi.h" + +struct usbh_msc { + struct usb_setup_packet *setup; + uint8_t intf; /* Data interface number */ + uint8_t sdchar; + usbh_epinfo_t bulkin; /* Bulk IN endpoint */ + usbh_epinfo_t bulkout; /* Bulk OUT endpoint */ + uint8_t *tx_buffer; + uint32_t blocknum; /* Number of blocks on the USB mass storage device */ + uint16_t blocksize; /* Block size of USB mass storage device */ +}; + +extern const struct usbh_class_driver msc_class_driver; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/tmc/usb_tmc.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/tmc/usb_tmc.h new file mode 100644 index 00000000..eb622b49 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/tmc/usb_tmc.h @@ -0,0 +1,130 @@ +/** + * @file + * @brief USB TMC Class public header + * + */ + +#ifndef _USB_TMC_H_ +#define _USB_TMC_H_ + +/**@addtogroup MODULE_TMC USB TMC class + * @brief This module contains USB Device Test and Measurement Class definitions. + * @details This module based on + * [USB Device Test and Measurement Class Specification, Revision 1.0] + * (https://www.usb.org/sites/default/files/USBTMC_1_006a.zip) + * @{*/ + +/**@name USB TMC class, subclass and protocol definitions + * @{*/ +#define TMC_SUBCLASS_TMC 0x03 +#define TMC_PROTOCOL_NONE 0x00 /**< No subclass specification applies. */ +#define TMC_PROTOCOL_USB488 0x01 /**< USBTMC USB488 subclass interface. */ +/** @}*/ + +/**@name USBTMC requests + * @{*/ +#define TMC_REQUEST_INITIATE_ABORT_BULK_OUT 1 +#define TMC_REQUEST_CHECK_ABORT_BULK_OUT_STATUS 2 +#define TMC_REQUEST_INITIATE_ABORT_BULK_IN 3 +#define TMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS 4 +#define TMC_REQUEST_INITIATE_CLEAR 5 +#define TMC_REQUEST_CHECK_CLEAR_STATUS 6 +#define TMC_REQUEST_GET_CAPABILITIES 7 +#define TMC_REQUEST_INDICATOR_PULSE 64 +/**@}*/ + +/**@name USBTMC status values + * @{*/ +#define TMC_STATUS_SUCCESS 0x01 +#define TMC_STATUS_PENDING 0x02 +#define TMC_STATUS_FAILED 0x80 +#define TMC_STATUS_TRANSFER_NOT_IN_PROGRESS 0x81 +#define TMC_STATUS_SPLIT_NOT_IN_PROGRESS 0x82 +#define TMC_STATUS_SPLIT_IN_PROGRESS 0x83 +/**@}*/ + +/** GET_CAPABILITIES request response */ +struct tmc_get_capabilities_response { + uint8_t USBTMC_status; + uint8_t Reserved0; + uint16_t bcdUSBTMC; + uint8_t InterfaceCapabilities; + uint8_t DeviceCapabilities; + uint8_t Reserved1[18]; +} __PACKED; + +/**@name MsgId values + * @{*/ +#define TMC_DEV_DEP_MSG_OUT 1 +#define TMC_REQUEST_DEV_DEP_MSG_IN 2 +#define TMC_DEV_DEP_MSG_IN 2 +#define TMC_VENDOR_SPECIFIC_OUT 126 +#define TMC_REQUEST_VENDOR_SPECIFIC_IN 127 +#define TMC_VENDOR_SPECIFIC_IN 127 +/**@}*/ + +/**@name Transfer Attributes + * @{*/ +/** The last USBTMC message data byte in the transfer is the last byte of the + * USBTMC message. */ +#define TMC_TRANSFER_ATTR_EOM 0x01 +/** The Bulk-IN transfer must terminate on the specified TermChar. The Host may + * only set this bit if the USBTMC interface indicates it supports TermChar in + * the GET_CAPABILITIES response packet */ +#define TMC_TRANSFER_ATTR_TERM_CHAR 0x02 +/**@}*/ + +/** Message specific part of bulk header */ +union usb_tmc_bulk_header_specific { + struct { + uint32_t TransferSize; + uint8_t bmTransferAttributes; + uint8_t Reserved[3]; + } dev_dep_msg_out; + + struct { + uint32_t TransferSize; + uint8_t bmTransferAttributes; + uint8_t TermChar; + uint8_t Reserved[2]; + } request_dev_dep_msg_in; + + struct { + uint32_t TransferSize; + uint8_t bmTransferAttributes; + uint8_t Reserved[3]; + } dev_dep_msg_in; + + struct { + uint32_t TransferSize; + uint8_t Reserved[4]; + } vendor_specific_out; + + struct { + uint32_t TransferSize; + uint8_t Reserved[4]; + } request_vendor_specific_in; + + struct { + uint32_t TransferSize; + uint8_t Reserved[4]; + } vendor_specific_in; +}; + +/** Host must begin the first USB transaction in each Bulk transfer of + * command message content with a Bulk Header. */ +struct usb_tmc_bulk_header { + /** Specifies the USBTMC message and the type of the USBTMC message. */ + uint8_t MsgId; + /** A transfer identifier. The Host must set bTag different than the + * bTag used in the previous Bulk-OUT Header. The Host should increment + * the bTag by 1 each time it sends a new Bulk-OUT Header. */ + uint8_t bTag; + /** The inverse (one's complement) of the bTag */ + uint8_t bTagInverse; + uint8_t Reserved; + /** USBTMC command message specific */ + union usb_tmc_bulk_header_specific MsgSpecific; +} __PACKED; + +#endif /* _USB_TMC_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usb_video.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usb_video.h new file mode 100644 index 00000000..a482bb88 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usb_video.h @@ -0,0 +1,1162 @@ +/** + * @file + * @brief USB Video Class public header + * + * Header follows below documentation: + * - USB Device Class Definition for Video Devices UVC 1.5 Class specification.pdf + */ + +#ifndef _USB_VIDEO_H_ +#define _USB_VIDEO_H_ + +#define USB_DEVICE_VIDEO_CLASS_VERSION_1_5 0 + +/*! @brief Video device subclass code */ +#define VIDEO_SC_UNDEFINED 0x00U +#define VIDEO_SC_VIDEOCONTROL 0x01U +#define VIDEO_SC_VIDEOSTREAMING 0x02U +#define VIDEO_SC_VIDEO_INTERFACE_COLLECTION 0x03U + +/*! @brief Video device protocol code */ +#define VIDEO_PC_PROTOCOL_UNDEFINED 0x00U +#define VIDEO_PC_PROTOCOL_15 0x01U + +/*! @brief Video device class-specific descriptor type */ +#define VIDEO_CS_UNDEFINED_DESCRIPTOR_TYPE 0x20U +#define VIDEO_CS_DEVICE_DESCRIPTOR_TYPE 0x21U +#define VIDEO_CS_CONFIGURATION_DESCRIPTOR_TYPE 0x22U +#define VIDEO_CS_STRING_DESCRIPTOR_TYPE 0x23U +#define VIDEO_CS_INTERFACE_DESCRIPTOR_TYPE 0x24U +#define VIDEO_CS_ENDPOINT_DESCRIPTOR_TYPE 0x25U + +/*! @brief Video device class-specific VC interface descriptor subtype */ +#define VIDEO_VC_DESCRIPTOR_UNDEFINED_DESCRIPTOR_SUBTYPE 0x00U +#define VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE 0x01U +#define VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE 0x02U +#define VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE 0x03U +#define VIDEO_VC_SELECTOR_UNIT_DESCRIPTOR_SUBTYPE 0x04U +#define VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE 0x05U +#define VIDEO_VC_EXTENSION_UNIT_DESCRIPTOR_SUBTYPE 0x06U +#define VIDEO_VC_ENCODING_UNIT_DESCRIPTOR_SUBTYPE 0x07U + +/*! @brief Video device class-specific VS interface descriptor subtype */ +#define VIDEO_VS_UNDEFINED_DESCRIPTOR_SUBTYPE 0x00U +#define VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE 0x01U +#define VIDEO_VS_OUTPUT_HEADER_DESCRIPTOR_SUBTYPE 0x02U +#define VIDEO_VS_STILL_IMAGE_FRAME_DESCRIPTOR_SUBTYPE 0x03U +#define VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_SUBTYPE 0x04U +#define VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE 0x05U +#define VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_SUBTYPE 0x06U +#define VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE 0x07U +#define VIDEO_VS_FORMAT_MPEG2TS_DESCRIPTOR_SUBTYPE 0x0AU +#define VIDEO_VS_FORMAT_DV_DESCRIPTOR_SUBTYPE 0x0CU +#define VIDEO_VS_COLORFORMAT_DESCRIPTOR_SUBTYPE 0x0DU +#define VIDEO_VS_FORMAT_FRAME_BASED_DESCRIPTOR_SUBTYPE 0x10U +#define VIDEO_VS_FRAME_FRAME_BASED_DESCRIPTOR_SUBTYPE 0x11U +#define VIDEO_VS_FORMAT_STREAM_BASED_DESCRIPTOR_SUBTYPE 0x12U +#define VIDEO_VS_FORMAT_H264_DESCRIPTOR_SUBTYPE 0x13U +#define VIDEO_VS_FRAME_H264_DESCRIPTOR_SUBTYPE 0x14U +#define VIDEO_VS_FORMAT_H264_SIMULCAST_DESCRIPTOR_SUBTYPE 0x15U +#define VIDEO_VS_FORMAT_VP8_DESCRIPTOR_SUBTYPE 0x16U +#define VIDEO_VS_FRAME_VP8_DESCRIPTOR_SUBTYPE 0x17U +#define VIDEO_VS_FORMAT_VP8_SIMULCAST_DESCRIPTOR_SUBTYPE 0x18U + +/*! @brief Video device class-specific VC endpoint descriptor subtype */ +#define VIDEO_EP_UNDEFINED_DESCRIPTOR_SUBTYPE 0x00U +#define VIDEO_EP_GENERAL_DESCRIPTOR_SUBTYPE 0x01U +#define VIDEO_EP_ENDPOINT_DESCRIPTOR_SUBTYPE 0x02U +#define VIDEO_EP_INTERRUPT_DESCRIPTOR_SUBTYPE 0x03U + +/*! @brief Video device class-specific request code */ +#define VIDEO_REQUEST_UNDEFINED 0x00U +#define VIDEO_REQUEST_SET_CUR 0x01U +#define VIDEO_REQUEST_SET_CUR_ALL 0x11U +#define VIDEO_REQUEST_GET_CUR 0x81U +#define VIDEO_REQUEST_GET_MIN 0x82U +#define VIDEO_REQUEST_GET_MAX 0x83U +#define VIDEO_REQUEST_GET_RES 0x84U +#define VIDEO_REQUEST_GET_LEN 0x85U +#define VIDEO_REQUEST_GET_INFO 0x86U +#define VIDEO_REQUEST_GET_DEF 0x87U +#define VIDEO_REQUEST_GET_CUR_ALL 0x91U +#define VIDEO_REQUEST_GET_MIN_ALL 0x92U +#define VIDEO_REQUEST_GET_MAX_ALL 0x93U +#define VIDEO_REQUEST_GET_RES_ALL 0x94U +#define VIDEO_REQUEST_GET_DEF_ALL 0x97U + +/*! @brief Video device class-specific VideoControl interface control selector */ +#define VIDEO_VC_CONTROL_UNDEFINED 0x00U +#define VIDEO_VC_VIDEO_POWER_MODE_CONTROL 0x01U +#define VIDEO_VC_REQUEST_ERROR_CODE_CONTROL 0x02U + +/*! @brief Video device class-specific Terminal control selector */ +#define VIDEO_TE_CONTROL_UNDEFINED 0x00U + +/*! @brief Video device class-specific Selector Unit control selector */ +#define VIDEO_SU_CONTROL_UNDEFINED 0x00U +#define VIDEO_SU_INPUT_SELECT_CONTROL 0x01U + +/*! @brief Video device class-specific Camera Terminal control selector */ +#define VIDEO_CT_CONTROL_UNDEFINED 0x00U +#define VIDEO_CT_SCANNING_MODE_CONTROL 0x01U +#define VIDEO_CT_AE_MODE_CONTROL 0x02U +#define VIDEO_CT_AE_PRIORITY_CONTROL 0x03U +#define VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04U +#define VIDEO_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05U +#define VIDEO_CT_FOCUS_ABSOLUTE_CONTROL 0x06U +#define VIDEO_CT_FOCUS_RELATIVE_CONTROL 0x07U +#define VIDEO_CT_FOCUS_AUTO_CONTROL 0x08U +#define VIDEO_CT_IRIS_ABSOLUTE_CONTROL 0x09U +#define VIDEO_CT_IRIS_RELATIVE_CONTROL 0x0AU +#define VIDEO_CT_ZOOM_ABSOLUTE_CONTROL 0x0BU +#define VIDEO_CT_ZOOM_RELATIVE_CONTROL 0x0CU +#define VIDEO_CT_PANTILT_ABSOLUTE_CONTROL 0x0DU +#define VIDEO_CT_PANTILT_RELATIVE_CONTROL 0x0EU +#define VIDEO_CT_ROLL_ABSOLUTE_CONTROL 0x0FU +#define VIDEO_CT_ROLL_RELATIVE_CONTROL 0x10U +#define VIDEO_CT_PRIVACY_CONTROL 0x11U +#define VIDEO_CT_FOCUS_SIMPLE_CONTROL 0x12U +#define VIDEO_CT_WINDOW_CONTROL 0x13U +#define VIDEO_CT_REGION_OF_INTEREST_CONTROL 0x14U + +/*! @brief Video device class-specific Processing Unit control selector */ +#define VIDEO_PU_CONTROL_UNDEFINED 0x00U +#define VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01U +#define VIDEO_PU_BRIGHTNESS_CONTROL 0x02U +#define VIDEO_PU_CONTRAST_CONTROL 0x03U +#define VIDEO_PU_GAIN_CONTROL 0x04U +#define VIDEO_PU_POWER_LINE_FREQUENCY_CONTROL 0x05U +#define VIDEO_PU_HUE_CONTROL 0x06U +#define VIDEO_PU_SATURATION_CONTROL 0x07U +#define VIDEO_PU_SHARPNESS_CONTROL 0x08U +#define VIDEO_PU_GAMMA_CONTROL 0x09U +#define VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0AU +#define VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0BU +#define VIDEO_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0CU +#define VIDEO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0DU +#define VIDEO_PU_DIGITAL_MULTIPLIER_CONTROL 0x0EU +#define VIDEO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0FU +#define VIDEO_PU_HUE_AUTO_CONTROL 0x10U +#define VIDEO_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11U +#define VIDEO_PU_ANALOG_LOCK_STATUS_CONTROL 0x12U +#define VIDEO_PU_CONTRAST_AUTO_CONTROL 0x13U + +/*! @brief Video device class-specific Encoding Unit control selector */ +#define VIDEO_EU_CONTROL_UNDEFINED 0x00U +#define VIDEO_EU_SELECT_LAYER_CONTROL 0x01U +#define VIDEO_EU_PROFILE_TOOLSET_CONTROL 0x02U +#define VIDEO_EU_VIDEO_RESOLUTION_CONTROL 0x03U +#define VIDEO_EU_MIN_FRAME_INTERVAL_CONTROL 0x04U +#define VIDEO_EU_SLICE_MODE_CONTROL 0x05U +#define VIDEO_EU_RATE_CONTROL_MODE_CONTROL 0x06U +#define VIDEO_EU_AVERAGE_BITRATE_CONTROL 0x07U +#define VIDEO_EU_CPB_SIZE_CONTROL 0x08U +#define VIDEO_EU_PEAK_BIT_RATE_CONTROL 0x09U +#define VIDEO_EU_QUANTIZATION_PARAMS_CONTROL 0x0AU +#define VIDEO_EU_SYNC_REF_FRAME_CONTROL 0x0BU +#define VIDEO_EU_LTR_BUFFER_CONTROL 0x0CU +#define VIDEO_EU_LTR_PICTURE_CONTROL 0x0DU +#define VIDEO_EU_LTR_VALIDATION_CONTROL 0x0EU +#define VIDEO_EU_LEVEL_IDC_LIMIT_CONTROL 0x0FU +#define VIDEO_EU_SEI_PAYLOADTYPE_CONTROL 0x10U +#define VIDEO_EU_QP_RANGE_CONTROL 0x11U +#define VIDEO_EU_PRIORITY_CONTROL 0x12U +#define VIDEO_EU_START_OR_STOP_LAYER_CONTROL 0x13U +#define VIDEO_EU_ERROR_RESILIENCY_CONTROL 0x14U + +/*! @brief Video device class-specific Extension Unit control selector */ +#define VIDEO_XU_CONTROL_UNDEFINED 0x00U + +/*! @brief Video device class-specific VideoStreaming Interface control selector */ +#define VIDEO_VS_CONTROL_UNDEFINED 0x00U +#define VIDEO_VS_PROBE_CONTROL 0x01U +#define VIDEO_VS_COMMIT_CONTROL 0x02U +#define VIDEO_VS_STILL_PROBE_CONTROL 0x03U +#define VIDEO_VS_STILL_COMMIT_CONTROL 0x04U +#define VIDEO_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05U +#define VIDEO_VS_STREAM_ERROR_CODE_CONTROL 0x06U +#define VIDEO_VS_GENERATE_KEY_FRAME_CONTROL 0x07U +#define VIDEO_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08U +#define VIDEO_VS_SYNCH_DELAY_CONTROL 0x09U + +/*! @}*/ + +/*! + * @name USB Video class terminal types + * @{ + */ + +/*! @brief Video device USB terminal type */ +#define VIDEO_TT_VENDOR_SPECIFIC 0x0100U +#define VIDEO_TT_STREAMING 0x0101U + +/*! @brief Video device input terminal type */ +#define VIDEO_ITT_VENDOR_SPECIFIC 0x0200U +#define VIDEO_ITT_CAMERA 0x0201U +#define VIDEO_ITT_MEDIA_TRANSPORT_INPUT 0x0202U + +/*! @brief Video device output terminal type */ +#define VIDEO_OTT_VENDOR_SPECIFIC 0x0300U +#define VIDEO_OTT_DISPLAY 0x0301U +#define VIDEO_OTT_MEDIA_TRANSPORT_OUTPUT 0x0302U + +/*! @brief Video device external terminal type */ +#define VIDEO_ET_VENDOR_SPECIFIC 0x0400U +#define VIDEO_ET_COMPOSITE_CONNECTOR 0x0401U +#define VIDEO_ET_SVIDEO_CONNECTOR 0x0402U +#define VIDEO_ET_COMPONENT_CONNECTOR 0x0403U + +/*! @}*/ + +/*! + * @name USB Video class setup request types + * @{ + */ + +/*! @brief Video device class setup request set type */ +#define VIDEO_SET_REQUEST_INTERFACE 0x21U +#define VIDEO_SET_REQUEST_ENDPOINT 0x22U + +/*! @brief Video device class setup request get type */ +#define VIDEO_GET_REQUEST_INTERFACE 0xA1U +#define VIDEO_GET_REQUEST_ENDPOINT 0xA2U + +/*! @}*/ + +/*! @brief Video device still image trigger control */ +#define VIDEO_STILL_IMAGE_TRIGGER_NORMAL_OPERATION 0x00U +#define VIDEO_STILL_IMAGE_TRIGGER_TRANSMIT_STILL_IMAGE 0x01U +#define VIDEO_STILL_IMAGE_TRIGGER_TRANSMIT_STILL_IMAGE_VS_DEDICATED_BULK_PIPE 0x02U +#define VIDEO_STILL_IMAGE_TRIGGER_ABORT_STILL_IMAGE_TRANSMISSION 0x03U + +/*! + * @name USB Video device class-specific request commands + * @{ + */ + +/*! @brief Video device class-specific request GET CUR COMMAND */ +#define VIDEO_GET_CUR_VC_POWER_MODE_CONTROL 0x8101U +#define VIDEO_GET_CUR_VC_ERROR_CODE_CONTROL 0x8102U + +#define VIDEO_GET_CUR_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8121U +#define VIDEO_GET_CUR_PU_BRIGHTNESS_CONTROL 0x8122U +#define VIDEO_GET_CUR_PU_CONTRACT_CONTROL 0x8123U +#define VIDEO_GET_CUR_PU_GAIN_CONTROL 0x8124U +#define VIDEO_GET_CUR_PU_POWER_LINE_FREQUENCY_CONTROL 0x8125U +#define VIDEO_GET_CUR_PU_HUE_CONTROL 0x8126U +#define VIDEO_GET_CUR_PU_SATURATION_CONTROL 0x8127U +#define VIDEO_GET_CUR_PU_SHARRNESS_CONTROL 0x8128U +#define VIDEO_GET_CUR_PU_GAMMA_CONTROL 0x8129U +#define VIDEO_GET_CUR_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x812AU +#define VIDEO_GET_CUR_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x812BU +#define VIDEO_GET_CUR_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x812CU +#define VIDEO_GET_CUR_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x812DU +#define VIDEO_GET_CUR_PU_DIGITAL_MULTIPLIER_CONTROL 0x812EU +#define VIDEO_GET_CUR_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x812FU +#define VIDEO_GET_CUR_PU_HUE_AUTO_CONTROL 0x8130U +#define VIDEO_GET_CUR_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x8131U +#define VIDEO_GET_CUR_PU_ANALOG_LOCK_STATUS_CONTROL 0x8132U +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_CUR_PU_CONTRAST_AUTO_CONTROL 0x8133U +#endif + +#define VIDEO_GET_CUR_CT_SCANNING_MODE_CONTROL 0x8141U +#define VIDEO_GET_CUR_CT_AE_MODE_CONTROL 0x8142U +#define VIDEO_GET_CUR_CT_AE_PRIORITY_CONTROL 0x8143U +#define VIDEO_GET_CUR_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8144U +#define VIDEO_GET_CUR_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x8145U +#define VIDEO_GET_CUR_CT_FOCUS_ABSOLUTE_CONTROL 0x8146U +#define VIDEO_GET_CUR_CT_FOCUS_RELATIVE_CONTROL 0x8147U +#define VIDEO_GET_CUR_CT_FOCUS_AUTO_CONTROL 0x8148U +#define VIDEO_GET_CUR_CT_IRIS_ABSOLUTE_CONTROL 0x8149U +#define VIDEO_GET_CUR_CT_IRIS_RELATIVE_CONTROL 0x814AU +#define VIDEO_GET_CUR_CT_ZOOM_ABSOLUTE_CONTROL 0x814BU +#define VIDEO_GET_CUR_CT_ZOOM_RELATIVE_CONTROL 0x814CU +#define VIDEO_GET_CUR_CT_PANTILT_ABSOLUTE_CONTROL 0x814DU +#define VIDEO_GET_CUR_CT_PANTILT_RELATIVE_CONTROL 0x814EU +#define VIDEO_GET_CUR_CT_ROLL_ABSOLUTE_CONTROL 0x814FU +#define VIDEO_GET_CUR_CT_ROLL_RELATIVE_CONTROL 0x8150U +#define VIDEO_GET_CUR_CT_PRIVACY_CONTROL 0x8151U +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_CUR_CT_FOCUS_SIMPLE_CONTROL 0x8152U +#define VIDEO_GET_CUR_CT_DIGITAL_WINDOW_CONTROL 0x8153U +#define VIDEO_GET_CUR_CT_REGION_OF_INTEREST_CONTROL 0x8154U +#endif + +#define VIDEO_GET_CUR_VS_PROBE_CONTROL 0x8161U +#define VIDEO_GET_CUR_VS_COMMIT_CONTROL 0x8162U +#define VIDEO_GET_CUR_VS_STILL_PROBE_CONTROL 0x8163U +#define VIDEO_GET_CUR_VS_STILL_COMMIT_CONTROL 0x8164U +#define VIDEO_GET_CUR_VS_STILL_IMAGE_TRIGGER_CONTROL 0x8165U +#define VIDEO_GET_CUR_VS_STREAM_ERROR_CODE_CONTROL 0x8166U +#define VIDEO_GET_CUR_VS_GENERATE_KEY_FRAME_CONTROL 0x8167U +#define VIDEO_GET_CUR_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8168U +#define VIDEO_GET_CUR_VS_SYNCH_DELAY_CONTROL 0x8169U + +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_CUR_EU_SELECT_LAYER_CONTROL 0x8181U +#define VIDEO_GET_CUR_EU_PROFILE_TOOLSET_CONTROL 0x8182U +#define VIDEO_GET_CUR_EU_VIDEO_RESOLUTION_CONTROL 0x8183U +#define VIDEO_GET_CUR_EU_MIN_FRAME_INTERVAL_CONTROL 0x8184U +#define VIDEO_GET_CUR_EU_SLICE_MODE_CONTROL 0x8185U +#define VIDEO_GET_CUR_EU_RATE_CONTROL_MODE_CONTROL 0x8186U +#define VIDEO_GET_CUR_EU_AVERAGE_BITRATE_CONTROL 0x8187U +#define VIDEO_GET_CUR_EU_CPB_SIZE_CONTROL 0x8188U +#define VIDEO_GET_CUR_EU_PEAK_BIT_RATE_CONTROL 0x8189U +#define VIDEO_GET_CUR_EU_QUANTIZATION_PARAMS_CONTROL 0x818AU +#define VIDEO_GET_CUR_EU_SYNC_REF_FRAME_CONTROL 0x818BU +#define VIDEO_GET_CUR_EU_LTR_BUFFER_CONTROL 0x818CU +#define VIDEO_GET_CUR_EU_LTR_PICTURE_CONTROL 0x818DU +#define VIDEO_GET_CUR_EU_LTR_VALIDATION_CONTROL 0x818EU +#define VIDEO_GET_CUR_EU_LEVEL_IDC_LIMIT_CONTROL 0x818FU +#define VIDEO_GET_CUR_EU_SEI_PAYLOADTYPE_CONTROL 0x8190U +#define VIDEO_GET_CUR_EU_QP_RANGE_CONTROL 0x8191U +#define VIDEO_GET_CUR_EU_PRIORITY_CONTROL 0x8192U +#define VIDEO_GET_CUR_EU_START_OR_STOP_LAYER_CONTROL 0x8193U +#define VIDEO_GET_CUR_EU_ERROR_RESILIENCY_CONTROL 0x8194U +#endif + +/*! @brief Video device class-specific request GET MIN COMMAND */ +#define VIDEO_GET_MIN_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8221U +#define VIDEO_GET_MIN_PU_BRIGHTNESS_CONTROL 0x8222U +#define VIDEO_GET_MIN_PU_CONTRACT_CONTROL 0x8223U +#define VIDEO_GET_MIN_PU_GAIN_CONTROL 0x8224U +#define VIDEO_GET_MIN_PU_HUE_CONTROL 0x8226U +#define VIDEO_GET_MIN_PU_SATURATION_CONTROL 0x8227U +#define VIDEO_GET_MIN_PU_SHARRNESS_CONTROL 0x8228U +#define VIDEO_GET_MIN_PU_GAMMA_CONTROL 0x8229U +#define VIDEO_GET_MIN_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x822AU +#define VIDEO_GET_MIN_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x822CU +#define VIDEO_GET_MIN_PU_DIGITAL_MULTIPLIER_CONTROL 0x822EU +#define VIDEO_GET_MIN_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x822FU + +#define VIDEO_GET_MIN_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8244U +#define VIDEO_GET_MIN_CT_FOCUS_ABSOLUTE_CONTROL 0x8246U +#define VIDEO_GET_MIN_CT_FOCUS_RELATIVE_CONTROL 0x8247U +#define VIDEO_GET_MIN_CT_IRIS_ABSOLUTE_CONTROL 0x8249U +#define VIDEO_GET_MIN_CT_ZOOM_ABSOLUTE_CONTROL 0x824BU +#define VIDEO_GET_MIN_CT_ZOOM_RELATIVE_CONTROL 0x824CU +#define VIDEO_GET_MIN_CT_PANTILT_ABSOLUTE_CONTROL 0x824DU +#define VIDEO_GET_MIN_CT_PANTILT_RELATIVE_CONTROL 0x824EU +#define VIDEO_GET_MIN_CT_ROLL_ABSOLUTE_CONTROL 0x824FU +#define VIDEO_GET_MIN_CT_ROLL_RELATIVE_CONTROL 0x8250U +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_MIN_CT_DIGITAL_WINDOW_CONTROL 0x8251U +#define VIDEO_GET_MIN_CT_REGION_OF_INTEREST_CONTROL 0x8252U +#endif + +#define VIDEO_GET_MIN_VS_PROBE_CONTROL 0x8261U +#define VIDEO_GET_MIN_VS_STILL_PROBE_CONTROL 0x8263U +#define VIDEO_GET_MIN_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8268U +#define VIDEO_GET_MIN_VS_SYNCH_DELAY_CONTROL 0x8269U + +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_MIN_EU_VIDEO_RESOLUTION_CONTROL 0x8283U +#define VIDEO_GET_MIN_EU_MIN_FRAME_INTERVAL_CONTROL 0x8284U +#define VIDEO_GET_MIN_EU_SLICE_MODE_CONTROL 0x8285U +#define VIDEO_GET_MIN_EU_AVERAGE_BITRATE_CONTROL 0x8287U +#define VIDEO_GET_MIN_EU_CPB_SIZE_CONTROL 0x8288U +#define VIDEO_GET_MIN_EU_PEAK_BIT_RATE_CONTROL 0x8289U +#define VIDEO_GET_MIN_EU_QUANTIZATION_PARAMS_CONTROL 0x828AU +#define VIDEO_GET_MIN_EU_SYNC_REF_FRAME_CONTROL 0x828BU +#define VIDEO_GET_MIN_EU_LEVEL_IDC_LIMIT_CONTROL 0x828FU +#define VIDEO_GET_MIN_EU_SEI_PAYLOADTYPE_CONTROL 0x8290U +#define VIDEO_GET_MIN_EU_QP_RANGE_CONTROL 0x8291U +#endif + +/*! @brief Video device class-specific request GET MAX COMMAND */ +#define VIDEO_GET_MAX_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8321U +#define VIDEO_GET_MAX_PU_BRIGHTNESS_CONTROL 0x8322U +#define VIDEO_GET_MAX_PU_CONTRACT_CONTROL 0x8323U +#define VIDEO_GET_MAX_PU_GAIN_CONTROL 0x8324U +#define VIDEO_GET_MAX_PU_HUE_CONTROL 0x8326U +#define VIDEO_GET_MAX_PU_SATURATION_CONTROL 0x8327U +#define VIDEO_GET_MAX_PU_SHARRNESS_CONTROL 0x8328U +#define VIDEO_GET_MAX_PU_GAMMA_CONTROL 0x8329U +#define VIDEO_GET_MAX_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x832AU +#define VIDEO_GET_MAX_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x832CU +#define VIDEO_GET_MAX_PU_DIGITAL_MULTIPLIER_CONTROL 0x832EU +#define VIDEO_GET_MAX_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x832FU + +#define VIDEO_GET_MAX_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8344U +#define VIDEO_GET_MAX_CT_FOCUS_ABSOLUTE_CONTROL 0x8346U +#define VIDEO_GET_MAX_CT_FOCUS_RELATIVE_CONTROL 0x8347U +#define VIDEO_GET_MAX_CT_IRIS_ABSOLUTE_CONTROL 0x8349U +#define VIDEO_GET_MAX_CT_ZOOM_ABSOLUTE_CONTROL 0x834BU +#define VIDEO_GET_MAX_CT_ZOOM_RELATIVE_CONTROL 0x834CU +#define VIDEO_GET_MAX_CT_PANTILT_ABSOLUTE_CONTROL 0x834DU +#define VIDEO_GET_MAX_CT_PANTILT_RELATIVE_CONTROL 0x834EU +#define VIDEO_GET_MAX_CT_ROLL_ABSOLUTE_CONTROL 0x834FU +#define VIDEO_GET_MAX_CT_ROLL_RELATIVE_CONTROL 0x8350U +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_MAX_CT_DIGITAL_WINDOW_CONTROL 0x8351U +#define VIDEO_GET_MAX_CT_REGION_OF_INTEREST_CONTROL 0x8352U +#endif + +#define VIDEO_GET_MAX_VS_PROBE_CONTROL 0x8361U +#define VIDEO_GET_MAX_VS_STILL_PROBE_CONTROL 0x8363U +#define VIDEO_GET_MAX_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8368U +#define VIDEO_GET_MAX_VS_SYNCH_DELAY_CONTROL 0x8369U + +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_MAX_EU_VIDEO_RESOLUTION_CONTROL 0x8383U +#define VIDEO_GET_MAX_EU_MIN_FRAME_INTERVAL_CONTROL 0x8384U +#define VIDEO_GET_MAX_EU_SLICE_MODE_CONTROL 0x8385U +#define VIDEO_GET_MAX_EU_AVERAGE_BITRATE_CONTROL 0x8387U +#define VIDEO_GET_MAX_EU_CPB_SIZE_CONTROL 0x8388U +#define VIDEO_GET_MAX_EU_PEAK_BIT_RATE_CONTROL 0x8389U +#define VIDEO_GET_MAX_EU_QUANTIZATION_PARAMS_CONTROL 0x838AU +#define VIDEO_GET_MAX_EU_SYNC_REF_FRAME_CONTROL 0x838BU +#define VIDEO_GET_MAX_EU_LTR_BUFFER_CONTROL 0x838CU +#define VIDEO_GET_MAX_EU_LEVEL_IDC_LIMIT_CONTROL 0x838FU +#define VIDEO_GET_MAX_EU_SEI_PAYLOADTYPE_CONTROL 0x8390U +#define VIDEO_GET_MAX_EU_QP_RANGE_CONTROL 0x8391U +#endif + +/*! @brief Video device class-specific request GET RES COMMAND */ +#define VIDEO_GET_RES_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8421U +#define VIDEO_GET_RES_PU_BRIGHTNESS_CONTROL 0x8422U +#define VIDEO_GET_RES_PU_CONTRACT_CONTROL 0x8423U +#define VIDEO_GET_RES_PU_GAIN_CONTROL 0x8424U +#define VIDEO_GET_RES_PU_HUE_CONTROL 0x8426U +#define VIDEO_GET_RES_PU_SATURATION_CONTROL 0x8427U +#define VIDEO_GET_RES_PU_SHARRNESS_CONTROL 0x8428U +#define VIDEO_GET_RES_PU_GAMMA_CONTROL 0x8429U +#define VIDEO_GET_RES_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x842AU +#define VIDEO_GET_RES_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x842CU +#define VIDEO_GET_RES_PU_DIGITAL_MULTIPLIER_CONTROL 0x842EU +#define VIDEO_GET_RES_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x842FU + +#define VIDEO_GET_RES_CT_AE_MODE_CONTROL 0x8442U +#define VIDEO_GET_RES_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8444U +#define VIDEO_GET_RES_CT_FOCUS_ABSOLUTE_CONTROL 0x8446U +#define VIDEO_GET_RES_CT_FOCUS_RELATIVE_CONTROL 0x8447U +#define VIDEO_GET_RES_CT_IRIS_ABSOLUTE_CONTROL 0x8449U +#define VIDEO_GET_RES_CT_ZOOM_ABSOLUTE_CONTROL 0x844BU +#define VIDEO_GET_RES_CT_ZOOM_RELATIVE_CONTROL 0x844CU +#define VIDEO_GET_RES_CT_PANTILT_ABSOLUTE_CONTROL 0x844DU +#define VIDEO_GET_RES_CT_PANTILT_RELATIVE_CONTROL 0x844EU +#define VIDEO_GET_RES_CT_ROLL_ABSOLUTE_CONTROL 0x844FU +#define VIDEO_GET_RES_CT_ROLL_RELATIVE_CONTROL 0x8450U + +#define VIDEO_GET_RES_VS_PROBE_CONTROL 0x8461U +#define VIDEO_GET_RES_VS_STILL_PROBE_CONTROL 0x8463U +#define VIDEO_GET_RES_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8468U +#define VIDEO_GET_RES_VS_SYNCH_DELAY_CONTROL 0x8469U + +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_RES_EU_AVERAGE_BITRATE_CONTROL 0x8487U +#define VIDEO_GET_RES_EU_CPB_SIZE_CONTROL 0x8488U +#define VIDEO_GET_RES_EU_PEAK_BIT_RATE_CONTROL 0x8489U +#define VIDEO_GET_RES_EU_QUANTIZATION_PARAMS_CONTROL 0x848AU +#define VIDEO_GET_RES_EU_ERROR_RESILIENCY_CONTROL 0x8494U +#endif + +/*! @brief Video device class-specific request GET LEN COMMAND */ + +#define VIDEO_GET_LEN_VS_PROBE_CONTROL 0x8561U +#define VIDEO_GET_LEN_VS_COMMIT_CONTROL 0x8562U +#define VIDEO_GET_LEN_VS_STILL_PROBE_CONTROL 0x8563U +#define VIDEO_GET_LEN_VS_STILL_COMMIT_CONTROL 0x8564U + +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_LEN_EU_SELECT_LAYER_CONTROL 0x8581U +#define VIDEO_GET_LEN_EU_PROFILE_TOOLSET_CONTROL 0x8582U +#define VIDEO_GET_LEN_EU_VIDEO_RESOLUTION_CONTROL 0x8583U +#define VIDEO_GET_LEN_EU_MIN_FRAME_INTERVAL_CONTROL 0x8584U +#define VIDEO_GET_LEN_EU_SLICE_MODE_CONTROL 0x8585U +#define VIDEO_GET_LEN_EU_RATE_CONTROL_MODE_CONTROL 0x8586U +#define VIDEO_GET_LEN_EU_AVERAGE_BITRATE_CONTROL 0x8587U +#define VIDEO_GET_LEN_EU_CPB_SIZE_CONTROL 0x8588U +#define VIDEO_GET_LEN_EU_PEAK_BIT_RATE_CONTROL 0x8589U +#define VIDEO_GET_LEN_EU_QUANTIZATION_PARAMS_CONTROL 0x858AU +#define VIDEO_GET_LEN_EU_SYNC_REF_FRAME_CONTROL 0x858BU +#define VIDEO_GET_LEN_EU_LTR_BUFFER_CONTROL 0x858CU +#define VIDEO_GET_LEN_EU_LTR_PICTURE_CONTROL 0x858DU +#define VIDEO_GET_LEN_EU_LTR_VALIDATION_CONTROL 0x858EU +#define VIDEO_GET_LEN_EU_QP_RANGE_CONTROL 0x8591U +#define VIDEO_GET_LEN_EU_PRIORITY_CONTROL 0x8592U +#define VIDEO_GET_LEN_EU_START_OR_STOP_LAYER_CONTROL 0x8593U +#endif + +/*! @brief Video device class-specific request GET INFO COMMAND */ +#define VIDEO_GET_INFO_VC_POWER_MODE_CONTROL 0x8601U +#define VIDEO_GET_INFO_VC_ERROR_CODE_CONTROL 0x8602U + +#define VIDEO_GET_INFO_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8621U +#define VIDEO_GET_INFO_PU_BRIGHTNESS_CONTROL 0x8622U +#define VIDEO_GET_INFO_PU_CONTRACT_CONTROL 0x8623U +#define VIDEO_GET_INFO_PU_GAIN_CONTROL 0x8624U +#define VIDEO_GET_INFO_PU_POWER_LINE_FREQUENCY_CONTROL 0x8625U +#define VIDEO_GET_INFO_PU_HUE_CONTROL 0x8626U +#define VIDEO_GET_INFO_PU_SATURATION_CONTROL 0x8627U +#define VIDEO_GET_INFO_PU_SHARRNESS_CONTROL 0x8628U +#define VIDEO_GET_INFO_PU_GAMMA_CONTROL 0x8629U +#define VIDEO_GET_INFO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x862AU +#define VIDEO_GET_INFO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x862BU +#define VIDEO_GET_INFO_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x862CU +#define VIDEO_GET_INFO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x862DU +#define VIDEO_GET_INFO_PU_DIGITAL_MULTIPLIER_CONTROL 0x862EU +#define VIDEO_GET_INFO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x862FU +#define VIDEO_GET_INFO_PU_HUE_AUTO_CONTROL 0x8630U +#define VIDEO_GET_INFO_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x8631U +#define VIDEO_GET_INFO_PU_ANALOG_LOCK_STATUS_CONTROL 0x8632U +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_INFO_PU_CONTRAST_AUTO_CONTROL 0x8633U +#endif + +#define VIDEO_GET_INFO_CT_SCANNING_MODE_CONTROL 0x8641U +#define VIDEO_GET_INFO_CT_AE_MODE_CONTROL 0x8642U +#define VIDEO_GET_INFO_CT_AE_PRIORITY_CONTROL 0x8643U +#define VIDEO_GET_INFO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8644U +#define VIDEO_GET_INFO_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x8645U +#define VIDEO_GET_INFO_CT_FOCUS_ABSOLUTE_CONTROL 0x8646U +#define VIDEO_GET_INFO_CT_FOCUS_RELATIVE_CONTROL 0x8647U +#define VIDEO_GET_INFO_CT_FOCUS_AUTO_CONTROL 0x8648U +#define VIDEO_GET_INFO_CT_IRIS_ABSOLUTE_CONTROL 0x8649U +#define VIDEO_GET_INFO_CT_IRIS_RELATIVE_CONTROL 0x864AU +#define VIDEO_GET_INFO_CT_ZOOM_ABSOLUTE_CONTROL 0x864BU +#define VIDEO_GET_INFO_CT_ZOOM_RELATIVE_CONTROL 0x864CU +#define VIDEO_GET_INFO_CT_PANTILT_ABSOLUTE_CONTROL 0x864DU +#define VIDEO_GET_INFO_CT_PANTILT_RELATIVE_CONTROL 0x864EU +#define VIDEO_GET_INFO_CT_ROLL_ABSOLUTE_CONTROL 0x864FU +#define VIDEO_GET_INFO_CT_ROLL_RELATIVE_CONTROL 0x8650U +#define VIDEO_GET_INFO_CT_PRIVACY_CONTROL 0x8651U +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_INFO_CT_FOCUS_SIMPLE_CONTROL 0x8652U +#endif + +#define VIDEO_GET_INFO_VS_PROBE_CONTROL 0x8661U +#define VIDEO_GET_INFO_VS_COMMIT_CONTROL 0x8662U +#define VIDEO_GET_INFO_VS_STILL_PROBE_CONTROL 0x8663U +#define VIDEO_GET_INFO_VS_STILL_COMMIT_CONTROL 0x8664U +#define VIDEO_GET_INFO_VS_STILL_IMAGE_TRIGGER_CONTROL 0x8665U +#define VIDEO_GET_INFO_VS_STREAM_ERROR_CODE_CONTROL 0x8666U +#define VIDEO_GET_INFO_VS_GENERATE_KEY_FRAME_CONTROL 0x8667U +#define VIDEO_GET_INFO_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8668U +#define VIDEO_GET_INFO_VS_SYNCH_DELAY_CONTROL 0x8669U + +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_INFO_EU_SELECT_LAYER_CONTROL 0x8681U +#define VIDEO_GET_INFO_EU_PROFILE_TOOLSET_CONTROL 0x8682U +#define VIDEO_GET_INFO_EU_VIDEO_RESOLUTION_CONTROL 0x8683U +#define VIDEO_GET_INFO_EU_MIN_FRAME_INTERVAL_CONTROL 0x8684U +#define VIDEO_GET_INFO_EU_SLICE_MODE_CONTROL 0x8685U +#define VIDEO_GET_INFO_EU_RATE_CONTROL_MODE_CONTROL 0x8686U +#define VIDEO_GET_INFO_EU_AVERAGE_BITRATE_CONTROL 0x8687U +#define VIDEO_GET_INFO_EU_CPB_SIZE_CONTROL 0x8688U +#define VIDEO_GET_INFO_EU_PEAK_BIT_RATE_CONTROL 0x8689U +#define VIDEO_GET_INFO_EU_QUANTIZATION_PARAMS_CONTROL 0x868AU +#define VIDEO_GET_INFO_EU_SYNC_REF_FRAME_CONTROL 0x868BU +#define VIDEO_GET_INFO_EU_LTR_BUFFER_CONTROL 0x868CU +#define VIDEO_GET_INFO_EU_LTR_PICTURE_CONTROL 0x868DU +#define VIDEO_GET_INFO_EU_LTR_VALIDATION_CONTROL 0x868EU +#define VIDEO_GET_INFO_EU_SEI_PAYLOADTYPE_CONTROL 0x8690U +#define VIDEO_GET_INFO_EU_QP_RANGE_CONTROL 0x8691U +#define VIDEO_GET_INFO_EU_PRIORITY_CONTROL 0x8692U +#define VIDEO_GET_INFO_EU_START_OR_STOP_LAYER_CONTROL 0x8693U +#endif + +/*! @brief Video device class-specific request GET DEF COMMAND */ +#define VIDEO_GET_DEF_PU_BACKLIGHT_COMPENSATION_CONTROL 0x8721U +#define VIDEO_GET_DEF_PU_BRIGHTNESS_CONTROL 0x8722U +#define VIDEO_GET_DEF_PU_CONTRACT_CONTROL 0x8723U +#define VIDEO_GET_DEF_PU_GAIN_CONTROL 0x8724U +#define VIDEO_GET_DEF_PU_POWER_LINE_FREQUENCY_CONTROL 0x8725U +#define VIDEO_GET_DEF_PU_HUE_CONTROL 0x8726U +#define VIDEO_GET_DEF_PU_SATURATION_CONTROL 0x8727U +#define VIDEO_GET_DEF_PU_SHARRNESS_CONTROL 0x8728U +#define VIDEO_GET_DEF_PU_GAMMA_CONTROL 0x8729U +#define VIDEO_GET_DEF_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x872AU +#define VIDEO_GET_DEF_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x872BU +#define VIDEO_GET_DEF_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x872CU +#define VIDEO_GET_DEF_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x872DU +#define VIDEO_GET_DEF_PU_DIGITAL_MULTIPLIER_CONTROL 0x872EU +#define VIDEO_GET_DEF_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x872FU +#define VIDEO_GET_DEF_PU_HUE_AUTO_CONTROL 0x8730U +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_DEF_PU_CONTRAST_AUTO_CONTROL 0x8731U +#endif + +#define VIDEO_GET_DEF_CT_AE_MODE_CONTROL 0x8742U +#define VIDEO_GET_DEF_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x8744U +#define VIDEO_GET_DEF_CT_FOCUS_ABSOLUTE_CONTROL 0x8746U +#define VIDEO_GET_DEF_CT_FOCUS_RELATIVE_CONTROL 0x8747U +#define VIDEO_GET_DEF_CT_FOCUS_AUTO_CONTROL 0x8748U +#define VIDEO_GET_DEF_CT_IRIS_ABSOLUTE_CONTROL 0x8749U +#define VIDEO_GET_DEF_CT_ZOOM_ABSOLUTE_CONTROL 0x874BU +#define VIDEO_GET_DEF_CT_ZOOM_RELATIVE_CONTROL 0x874CU +#define VIDEO_GET_DEF_CT_PANTILT_ABSOLUTE_CONTROL 0x874DU +#define VIDEO_GET_DEF_CT_PANTILT_RELATIVE_CONTROL 0x874EU +#define VIDEO_GET_DEF_CT_ROLL_ABSOLUTE_CONTROL 0x874FU +#define VIDEO_GET_DEF_CT_ROLL_RELATIVE_CONTROL 0x8750U +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_DEF_CT_FOCUS_SIMPLE_CONTROL 0x8751U +#define VIDEO_GET_DEF_CT_DIGITAL_WINDOW_CONTROL 0x8752U +#define VIDEO_GET_DEF_CT_REGION_OF_INTEREST_CONTROL 0x8753U +#endif + +#define VIDEO_GET_DEF_VS_PROBE_CONTROL 0x8761U +#define VIDEO_GET_DEF_VS_STILL_PROBE_CONTROL 0x8763U +#define VIDEO_GET_DEF_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x8768U +#define VIDEO_GET_DEF_VS_SYNCH_DELAY_CONTROL 0x8769U + +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_GET_DEF_EU_PROFILE_TOOLSET_CONTROL 0x8782U +#define VIDEO_GET_DEF_EU_VIDEO_RESOLUTION_CONTROL 0x8783U +#define VIDEO_GET_DEF_EU_MIN_FRAME_INTERVAL_CONTROL 0x8784U +#define VIDEO_GET_DEF_EU_SLICE_MODE_CONTROL 0x8785U +#define VIDEO_GET_DEF_EU_RATE_CONTROL_MODE_CONTROL 0x8786U +#define VIDEO_GET_DEF_EU_AVERAGE_BITRATE_CONTROL 0x8787U +#define VIDEO_GET_DEF_EU_CPB_SIZE_CONTROL 0x8788U +#define VIDEO_GET_DEF_EU_PEAK_BIT_RATE_CONTROL 0x8789U +#define VIDEO_GET_DEF_EU_QUANTIZATION_PARAMS_CONTROL 0x878AU +#define VIDEO_GET_DEF_EU_LTR_BUFFER_CONTROL 0x878CU +#define VIDEO_GET_DEF_EU_LTR_PICTURE_CONTROL 0x878DU +#define VIDEO_GET_DEF_EU_LTR_VALIDATION_CONTROL 0x878EU +#define VIDEO_GET_DEF_EU_LEVEL_IDC_LIMIT_CONTROL 0x878FU +#define VIDEO_GET_DEF_EU_SEI_PAYLOADTYPE_CONTROL 0x8790U +#define VIDEO_GET_DEF_EU_QP_RANGE_CONTROL 0x8791U +#define VIDEO_GET_DEF_EU_ERROR_RESILIENCY_CONTROL 0x8794U +#endif + +/*! @brief Video device class-specific request SET CUR COMMAND */ +#define VIDEO_SET_CUR_VC_POWER_MODE_CONTROL 0x0101U + +#define VIDEO_SET_CUR_PU_BACKLIGHT_COMPENSATION_CONTROL 0x0121U +#define VIDEO_SET_CUR_PU_BRIGHTNESS_CONTROL 0x0122U +#define VIDEO_SET_CUR_PU_CONTRACT_CONTROL 0x0123U +#define VIDEO_SET_CUR_PU_GAIN_CONTROL 0x0124U +#define VIDEO_SET_CUR_PU_POWER_LINE_FREQUENCY_CONTROL 0x0125U +#define VIDEO_SET_CUR_PU_HUE_CONTROL 0x0126U +#define VIDEO_SET_CUR_PU_SATURATION_CONTROL 0x0127U +#define VIDEO_SET_CUR_PU_SHARRNESS_CONTROL 0x0128U +#define VIDEO_SET_CUR_PU_GAMMA_CONTROL 0x0129U +#define VIDEO_SET_CUR_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x012AU +#define VIDEO_SET_CUR_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x012BU +#define VIDEO_SET_CUR_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x012CU +#define VIDEO_SET_CUR_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x012DU +#define VIDEO_SET_CUR_PU_DIGITAL_MULTIPLIER_CONTROL 0x012EU +#define VIDEO_SET_CUR_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x012FU +#define VIDEO_SET_CUR_PU_HUE_AUTO_CONTROL 0x0130U +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_SET_CUR_PU_CONTRAST_AUTO_CONTROL 0x0131U +#endif + +#define VIDEO_SET_CUR_CT_SCANNING_MODE_CONTROL 0x0141U +#define VIDEO_SET_CUR_CT_AE_MODE_CONTROL 0x0142U +#define VIDEO_SET_CUR_CT_AE_PRIORITY_CONTROL 0x0143U +#define VIDEO_SET_CUR_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x0144U +#define VIDEO_SET_CUR_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x0145U +#define VIDEO_SET_CUR_CT_FOCUS_ABSOLUTE_CONTROL 0x0146U +#define VIDEO_SET_CUR_CT_FOCUS_RELATIVE_CONTROL 0x0147U +#define VIDEO_SET_CUR_CT_FOCUS_AUTO_CONTROL 0x0148U +#define VIDEO_SET_CUR_CT_IRIS_ABSOLUTE_CONTROL 0x0149U +#define VIDEO_SET_CUR_CT_IRIS_RELATIVE_CONTROL 0x014AU +#define VIDEO_SET_CUR_CT_ZOOM_ABSOLUTE_CONTROL 0x014BU +#define VIDEO_SET_CUR_CT_ZOOM_RELATIVE_CONTROL 0x014CU +#define VIDEO_SET_CUR_CT_PANTILT_ABSOLUTE_CONTROL 0x014DU +#define VIDEO_SET_CUR_CT_PANTILT_RELATIVE_CONTROL 0x014EU +#define VIDEO_SET_CUR_CT_ROLL_ABSOLUTE_CONTROL 0x014FU +#define VIDEO_SET_CUR_CT_ROLL_RELATIVE_CONTROL 0x0150U +#define VIDEO_SET_CUR_CT_PRIVACY_CONTROL 0x0151U +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_SET_CUR_CT_FOCUS_SIMPLE_CONTROL 0x0152U +#define VIDEO_SET_CUR_CT_DIGITAL_WINDOW_CONTROL 0x0153U +#define VIDEO_SET_CUR_CT_REGION_OF_INTEREST_CONTROL 0x0154U +#endif + +#define VIDEO_SET_CUR_VS_PROBE_CONTROL 0x0161U +#define VIDEO_SET_CUR_VS_COMMIT_CONTROL 0x0162U +#define VIDEO_SET_CUR_VS_STILL_PROBE_CONTROL 0x0163U +#define VIDEO_SET_CUR_VS_STILL_COMMIT_CONTROL 0x0164U +#define VIDEO_SET_CUR_VS_STILL_IMAGE_TRIGGER_CONTROL 0x0165U +#define VIDEO_SET_CUR_VS_STREAM_ERROR_CODE_CONTROL 0x0166U +#define VIDEO_SET_CUR_VS_GENERATE_KEY_FRAME_CONTROL 0x0167U +#define VIDEO_SET_CUR_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x0168U +#define VIDEO_SET_CUR_VS_SYNCH_DELAY_CONTROL 0x0169U + +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 +#define VIDEO_SET_CUR_EU_SELECT_LAYER_CONTROL 0x0181U +#define VIDEO_SET_CUR_EU_PROFILE_TOOLSET_CONTROL 0x0182U +#define VIDEO_SET_CUR_EU_VIDEO_RESOLUTION_CONTROL 0x0183U +#define VIDEO_SET_CUR_EU_MIN_FRAME_INTERVAL_CONTROL 0x0184U +#define VIDEO_SET_CUR_EU_SLICE_MODE_CONTROL 0x0185U +#define VIDEO_SET_CUR_EU_RATE_CONTROL_MODE_CONTROL 0x0186U +#define VIDEO_SET_CUR_EU_AVERAGE_BITRATE_CONTROL 0x0187U +#define VIDEO_SET_CUR_EU_CPB_SIZE_CONTROL 0x0188U +#define VIDEO_SET_CUR_EU_PEAK_BIT_RATE_CONTROL 0x0189U +#define VIDEO_SET_CUR_EU_QUANTIZATION_PARAMS_CONTROL 0x018AU +#define VIDEO_SET_CUR_EU_SYNC_REF_FRAME_CONTROL 0x018BU +#define VIDEO_SET_CUR_EU_LTR_BUFFER_CONTROL 0x018CU +#define VIDEO_SET_CUR_EU_LTR_PICTURE_CONTROL 0x018DU +#define VIDEO_SET_CUR_EU_LTR_VALIDATION_CONTROL 0x018EU +#define VIDEO_SET_CUR_EU_LEVEL_IDC_LIMIT_CONTROL 0x018FU +#define VIDEO_SET_CUR_EU_SEI_PAYLOADTYPE_CONTROL 0x0190U +#define VIDEO_SET_CUR_EU_QP_RANGE_CONTROL 0x0191U +#define VIDEO_SET_CUR_EU_PRIORITY_CONTROL 0x0192U +#define VIDEO_SET_CUR_EU_START_OR_STOP_LAYER_CONTROL 0x0193U +#define VIDEO_SET_CUR_EU_ERROR_RESILIENCY_CONTROL 0x0194U +#endif + +/*! @brief The payload header structure for MJPEG payload format. */ +struct video_mjpeg_payload_header { + uint8_t bHeaderLength; /*!< The payload header length. */ + union { + uint8_t bmheaderInfo; /*!< The payload header bitmap field. */ + struct + { + uint8_t frameIdentifier : 1U; /*!< Frame Identifier. This bit toggles at each frame start boundary and stays + constant for the rest of the frame.*/ + uint8_t endOfFrame : 1U; /*!< End of Frame. This bit indicates the end of a video frame and is set in the + last video sample that belongs to a frame.*/ + uint8_t + presentationTimeStamp : 1U; /*!< Presentation Time Stamp. This bit, when set, indicates the presence of + a PTS field.*/ + uint8_t sourceClockReference : 1U; /*!< Source Clock Reference. This bit, when set, indicates the presence + of a SCR field.*/ + uint8_t reserved : 1U; /*!< Reserved. Set to 0. */ + uint8_t stillImage : 1U; /*!< Still Image. This bit, when set, identifies a video sample that belongs to a + still image.*/ + uint8_t errorBit : 1U; /*!< Error Bit. This bit, when set, indicates an error in the device streaming.*/ + uint8_t endOfHeader : 1U; /*!< End of Header. This bit, when set, indicates the end of the BFH fields.*/ + } headerInfoBits; + struct + { + uint8_t FID : 1U; /*!< Frame Identifier. This bit toggles at each frame start boundary and stays constant + for the rest of the frame.*/ + uint8_t EOI : 1U; /*!< End of Frame. This bit indicates the end of a video frame and is set in the last + video sample that belongs to a frame.*/ + uint8_t PTS : 1U; /*!< Presentation Time Stamp. This bit, when set, indicates the presence of a PTS field.*/ + uint8_t SCR : 1U; /*!< Source Clock Reference. This bit, when set, indicates the presence of a SCR field.*/ + uint8_t RES : 1U; /*!< Reserved. Set to 0. */ + uint8_t STI : 1U; /*!< Still Image. This bit, when set, identifies a video sample that belongs to a still + image.*/ + uint8_t ERR : 1U; /*!< Error Bit. This bit, when set, indicates an error in the device streaming.*/ + uint8_t EOH : 1U; /*!< End of Header. This bit, when set, indicates the end of the BFH fields.*/ + } headerInfoBitmap; + } headerInfoUnion; + uint32_t dwPresentationTime; /*!< Presentation time stamp (PTS) field.*/ + uint8_t bSourceClockReference[6]; /*!< Source clock reference (SCR) field.*/ +} __PACKED; + +/*! @brief The Video probe and commit controls structure.*/ +struct video_probe_and_commit_controls { + union { + uint8_t bmHint; /*!< Bit-field control indicating to the function what fields shall be kept fixed. */ + struct + { + uint8_t dwFrameInterval : 1U; /*!< dwFrameInterval field.*/ + uint8_t wKeyFrameRate : 1U; /*!< wKeyFrameRate field.*/ + uint8_t wPFrameRate : 1U; /*!< wPFrameRate field.*/ + uint8_t wCompQuality : 1U; /*!< wCompQuality field.*/ + uint8_t wCompWindowSize : 1U; /*!< wCompWindowSize field.*/ + uint8_t reserved : 3U; /*!< Reserved field.*/ + } hintBitmap; + } hintUnion; + union { + uint8_t bmHint; /*!< Bit-field control indicating to the function what fields shall be kept fixed. */ + struct + { + uint8_t reserved : 8U; /*!< Reserved field.*/ + } hintBitmap; + } hintUnion1; + uint8_t bFormatIndex; /*!< Video format index from a format descriptor.*/ + uint8_t bFrameIndex; /*!< Video frame index from a frame descriptor.*/ + uint32_t dwFrameInterval; /*!< Frame interval in 100ns units.*/ + uint16_t wKeyFrameRate; /*!< Key frame rate in key-frame per video-frame units.*/ + uint16_t wPFrameRate; /*!< PFrame rate in PFrame/key frame units.*/ + uint16_t wCompQuality; /*!< Compression quality control in abstract units 0U (lowest) to 10000U (highest).*/ + uint16_t wCompWindowSize; /*!< Window size for average bit rate control.*/ + uint16_t wDelay; /*!< Internal video streaming interface latency in ms from video data capture to presentation on + the USB.*/ + uint32_t dwMaxVideoFrameSize; /*!< Maximum video frame or codec-specific segment size in bytes.*/ + uint32_t dwMaxPayloadTransferSize; /*!< Specifies the maximum number of bytes that the device can transmit or + receive in a single payload transfer.*/ + uint32_t dwClockFrequency; /*!< The device clock frequency in Hz for the specified format. This specifies the + units used for the time information fields in the Video Payload Headers in the data + stream.*/ + uint8_t bmFramingInfo; /*!< Bit-field control supporting the following values: D0 Frame ID, D1 EOF.*/ + uint8_t bPreferedVersion; /*!< The preferred payload format version supported by the host or device for the + specified bFormatIndex value.*/ + uint8_t bMinVersion; /*!< The minimum payload format version supported by the device for the specified bFormatIndex + value.*/ + uint8_t bMaxVersion; /*!< The maximum payload format version supported by the device for the specified bFormatIndex + value.*/ +#if defined(USB_DEVICE_VIDEO_CLASS_VERSION_1_5) && USB_DEVICE_VIDEO_CLASS_VERSION_1_5 + uint8_t bUsage; /*!< This bitmap enables features reported by the bmUsages field of the Video Frame Descriptor.*/ + uint8_t + bBitDepthLuma; /*!< Represents bit_depth_luma_minus8 + 8U, which must be the same as bit_depth_chroma_minus8 + + 8.*/ + uint8_t bmSettings; /*!< A bitmap of flags that is used to discover and control specific features of a temporally + encoded video stream.*/ + uint8_t bMaxNumberOfRefFramesPlus1; /*!< Host indicates the maximum number of frames stored for use as references.*/ + uint16_t bmRateControlModes; /*!< This field contains 4U sub-fields, each of which is a 4U bit number.*/ + uint64_t bmLayoutPerStream; /*!< This field contains 4U sub-fields, each of which is a 2U byte number.*/ +#endif +} __PACKED; + +/*! @brief The Video still probe and still commit controls structure.*/ +struct video_still_probe_and_commit_controls { + uint8_t bFormatIndex; /*!< Video format index from a format descriptor.*/ + uint8_t bFrameIndex; /*!< Video frame index from a frame descriptor.*/ + uint8_t bCompressionIndex; /*!< Compression index from a frame descriptor.*/ + uint32_t dwMaxVideoFrameSize; /*!< Maximum still image size in bytes.*/ + uint32_t dwMaxPayloadTransferSize; /*!< Specifies the maximum number of bytes that the device can transmit or + receive in a single payload transfer.*/ +} __PACKED; + +struct video_cs_if_vc_header_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdVDC; + uint16_t wTotalLength; + uint32_t dwClockFrequency; + uint8_t bInCollection; + uint8_t baInterfaceNr[]; +} __PACKED; + +#define VIDEO_SIZEOF_VC_HEADER_DESC(n) (12 + n) + +struct video_cs_if_vc_input_terminal_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bTerminalID; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t iTerminal; + uint16_t wObjectiveFocalLenMin; + uint16_t wObjectiveFocalLenMax; + uint16_t wOcularFocalLength; + uint8_t bControlSize; + uint8_t bmaControls[]; +} __PACKED; + +#define VIDEO_SIZEOF_VC_INPUT_TERMINAL_DESC(n) (15 + n) + +struct video_cs_if_vc_processing_unit_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bUnitID; + uint8_t bSourceID; + uint16_t wMaxMultiplier; + uint8_t bControlSize; + uint8_t bmaControls[2]; + uint8_t iProcessing; + uint8_t bmVideoStandards; +} __PACKED; + +#define VIDEO_SIZEOF_VC_PROCESSING_UNIT_DESC(n) (10 + n) + +struct video_cs_if_vc_output_terminal_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bTerminalID; + uint16_t wTerminalType; + uint8_t bAssocTerminal; + uint8_t bSourceID; + uint8_t iTerminal; +} __PACKED; + +#define VIDEO_SIZEOF_VC_OUTPUT_TERMINAL_DESC 9 + +struct video_cs_ep_vc_ep_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint16_t wMaxTransferSize; +} __PACKED; + +#define VIDEO_SIZEOF_VC_EP_DESC 5 + +struct video_cs_if_vs_input_header_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bNumFormats; + uint16_t wTotalLength; + uint8_t bEndpointAddress; + uint8_t bmInfo; + uint8_t bTerminalLink; + uint8_t bStillCaptureMethod; + uint8_t bTriggerSupport; + uint8_t bTriggerUsage; + uint8_t bControlSize; + uint8_t bmaControls[]; +} __PACKED; + +#define VIDEO_SIZEOF_VS_INPUT_HEADER_DESC(p, n) (13 + p * n) + +struct video_cs_if_vs_output_header_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bNumFormats; + uint16_t wTotalLength; + uint8_t bEndpointAddress; + uint8_t bTerminalLink; + uint8_t bControlSize; + uint8_t bmaControls[]; +} __PACKED; + +#define VIDEO_SIZEOF_VS_OUTPUT_TERMINAL_DESC(p, n) (9 + p * n) + +struct video_cs_if_vs_format_uncompressed_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bFormatIndex; + uint8_t bNumFrameDescriptors; + uint32_t guidFormat; + uint8_t bBitsPerPixel; + uint8_t bDefaultFrameIndex; + uint8_t bAspectRatioX; + uint8_t bAspectRatioY; + uint8_t bmInterlaceFlags; + uint8_t bCopyProtect; +} __PACKED; + +#define VIDEO_SIZEOF_VS_FORMAT_UNCOMPRESSED_DESC(n) (11 + n) + +struct video_cs_if_vs_frame_uncompressed_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bFormatIndex; + uint8_t bmCapabilities; + uint16_t wWidth; + uint16_t wHeight; + uint32_t dwMinBitRate; + uint32_t dwMaxBitRate; + uint32_t dwMaxVideoFrameBufferSize; + uint32_t dwDefaultFrameInterval; + uint8_t bFrameIntervalType; + uint32_t dwFrameInterval; +} __PACKED; + +#define VIDEO_SIZEOF_VS_FRAME_UNCOMPRESSED_DESC 30 + +struct video_cs_if_vs_format_mjpeg_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bFormatIndex; + uint8_t bNumFrameDescriptors; + uint8_t bmFlags; + uint8_t bDefaultFrameIndex; + uint8_t bAspectRatioX; + uint8_t bAspectRatioY; + uint8_t bmInterlaceFlags; + uint8_t bCopyProtect; +} __PACKED; + +#define VIDEO_SIZEOF_VS_FORMAT_MJPEG_DESC 11 + +struct video_cs_if_vs_frame_mjpeg_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bFormatIndex; + uint8_t bmCapabilities; + uint16_t wWidth; + uint16_t wHeight; + uint32_t dwMinBitRate; + uint32_t dwMaxBitRate; + uint32_t dwMaxVideoFrameBufferSize; + uint32_t dwDefaultFrameInterval; + uint8_t bFrameIntervalType; + uint32_t dwFrameInterval1; + uint32_t dwFrameInterval2; +} __PACKED; + +#define VIDEO_SIZEOF_VS_FRAME_MJPEG_DESC 34 + +struct video_cs_if_vs_colorformat_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint8_t bColorPrimaries; + uint8_t bXferCharacteristics; + uint8_t bMatrixCoefficients; +} __PACKED; + +#define VIDEO_SIZEOF_VS_COLORFORMAT_DESC 6 + +struct video_vc_input_terminal_bmcontrol_bitmap { + uint32_t scanning_mode : 1; + uint32_t auto_exposure_mode : 1; + uint32_t auto_exposure_priority : 1; + uint32_t exposure_time_absolute : 1; + uint32_t exposure_time_relative : 1; + uint32_t focus_absolute : 1; + uint32_t focus_relative : 1; + uint32_t iris_absolute : 1; + uint32_t iris_relative : 1; + uint32_t zoom_absolute : 1; + uint32_t zoom_relative : 1; + uint32_t pantilt_absolute : 1; + uint32_t pantilt_relative : 1; + uint32_t roll_absolute : 1; + uint32_t roll_relative : 1; + uint32_t reserved : 2; + uint32_t focus_auto : 1; + uint32_t pricvcy : 1; +}; + +struct video_vc_processing_unit_bmcontrol_bitmap { + uint16_t brightness : 1; + uint16_t contrast : 1; + uint16_t hue : 1; + uint16_t saturation : 1; + uint16_t sharpness : 1; + uint16_t gamma : 1; + uint16_t white_bal_temp : 1; + uint16_t white_bal_comp : 1; + uint16_t backlight_comp : 1; + uint16_t gain : 1; + uint16_t power_line_freq : 1; + uint16_t hue_auto : 1; + uint16_t white_bal_temp_auto : 1; + uint16_t white_bal_comp_auto : 1; + uint16_t digital_mult : 1; + uint16_t digital_mult_limit : 1; +}; + +struct video_camera_capabilities { + uint8_t support_get_request : 1; + uint8_t support_set_request : 1; + uint8_t disabled_by_automatic_mode : 1; + uint8_t auto_update_control : 1; + uint8_t async_control : 1; + uint8_t reserved : 3; +}; + +struct video_autoexposure_mode { + uint8_t manual_mode : 1; + uint8_t auto_mode : 1; + uint8_t shutter_priority_mode : 1; + uint8_t aperture_priority_mode : 1; + uint8_t reserved : 4; +}; + +struct video_entity_info { + usb_slist_t list; + uint8_t bDescriptorSubtype; + uint8_t bEntityId; + uint16_t wTerminalType; +}; + +// clang-format off +#define VIDEO_VC_DESCRIPTOR_INIT(bFirstInterface, bNumEndpoints, bcdUVC, wTotalLength, dwClockFrequency, stridx) \ + /* Interface Association Descriptor */ \ + 0x08, \ + USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, \ + bFirstInterface, \ + 0x02, \ + USB_DEVICE_CLASS_VIDEO, \ + VIDEO_SC_VIDEO_INTERFACE_COLLECTION, \ + 0x00, \ + 0x00, /* VideoControl Interface Descriptor */ \ + 0x09, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ + 0x00, /* bInterfaceNumber */ \ + 0x00, /* bAlternateSetting */ \ + bNumEndpoints, /* bNumEndpoints:1 endpoint (interrupt endpoint) */ \ + USB_DEVICE_CLASS_VIDEO, /* bInterfaceClass : CC_VIDEO */ \ + VIDEO_SC_VIDEOCONTROL, /* bInterfaceSubClass : SC_VIDEOCONTROL */ \ + VIDEO_PC_PROTOCOL_UNDEFINED, /* bInterfaceProtocol : PC_PROTOCOL_UNDEFINED */ \ + stridx, /* iInterface:Index to string descriptor that contains the string */ \ + /*Class-specific VideoControl Interface Descriptor */ \ + 0x0d, /* bLength */ \ + 0x24, /* bDescriptorType : CS_INTERFACE */ \ + VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VC_HEADER subtype */ \ + WBVAL(bcdUVC), /* bcdUVC : Revision of class specification that this device is based upon.*/ \ + WBVAL(wTotalLength), /* wTotalLength */ \ + DBVAL(dwClockFrequency), /* dwClockFrequency : 0x005b8d80 -> 6,000,000 == 6MHz*/ \ + 0x01, /* bInCollection : Number of streaming interfaces. */ \ + 0x01, /* baInterfaceNr(1) : VideoStreaming interface 1 belongs to this VideoControl interface.*/ \ + /* Input Terminal 1 -> Processing Unit 2 -> Output Terminal 3 */ \ + 0x12, \ + 0x24, \ + VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \ + 0x01, /* bTerminalID */ \ + WBVAL(VIDEO_ITT_CAMERA), /* wTerminalType : 0x0201 Camera Sensor*/ \ + 0x00, /* bAssocTerminal */ \ + 0x00, /* iTerminal */ \ + WBVAL(0x0000), /* wObjectiveFocalLengthMin */ \ + WBVAL(0x0000), /* wObjectiveFocalLengthMax */ \ + WBVAL(0x0000), /* wOcularFocalLength */ \ + 0x03, /* bControlSize */ \ + 0x00, 0x00, 0x00, /* bmControls */ \ + 0x0c, \ + 0x24, \ + VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE, \ + 0x02, /* bUnitID */ \ + 0x01, /* bSourceID */ \ + 0x00, 0x40, /* wMaxMultiplier */ \ + 0x02, /* bControlSize */ \ + 0x00, 0x00, /* bmControls */ \ + 0x00, /* iProcessing */ \ + 0x00, /* bmVideoStandards */ \ + 0x09, \ + 0x24, \ + VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE, \ + 0x03, /* iProcessing */ \ + WBVAL(VIDEO_TT_STREAMING), \ + 0x00, /* bAssocTerminal */ \ + 0x02, /* bSourceID */ \ + 0x00 /* iTerminal */ + +#define VIDEO_VS_HEADER_DESCRIPTOR_INIT(bNumFormats, wTotalLength, bEndpointAddress) \ + /*Class-specific VideoStream Header Descriptor (Input) */ \ + 0x10, \ + 0x24, \ + VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE, \ + bNumFormats, /* bNumFormats : One format descriptor follows. */ \ + WBVAL(wTotalLength), \ + bEndpointAddress, \ + 0x00, /* bmInfo : No dynamic format change supported. */ \ + 0x03, /* bTerminalLink : This VideoStreaming interface supplies terminal ID 3 (Output Terminal). */ \ + 0x00, /* bStillCaptureMethod : Device supports still image capture method 0. */ \ + 0x00, /* bTriggerSupport : Hardware trigger supported for still image capture */ \ + 0x00, /* bTriggerUsage : Hardware trigger should initiate a still image capture. */ \ + 0x01, /* bControlSize : Size of the bmaControls field */ \ + 0x00, 0x04, 0x00 /* bmaControls : No VideoStreaming specific controls are supported.*/ \ + +#define VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \ + dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, dwFrameInterval) \ + 0x1e, \ + 0x24, \ + VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE, \ + bFrameIndex, \ + 0x00, \ + WBVAL(wWidth), \ + WBVAL(wHeight), \ + DBVAL(dwMinBitRate), \ + DBVAL(dwMaxBitRate), \ + DBVAL(dwMaxVideoFrameBufferSize), \ + DBVAL(dwDefaultFrameInterval), \ + 0x01, \ + DBVAL(dwFrameInterval) + +#define VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(bFrameIndex, wWidth, wHeight, dwMinBitRate, dwMaxBitRate, \ + dwMaxVideoFrameBufferSize, dwDefaultFrameInterval, dwMinFrameInterval1, dwMinFrameInterval2) \ + 0x22, /* bLength */ \ + 0x24, /* bDescriptorType : CS_INTERFACE */ \ + VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE, /* bDescriptorSubType : VS_FRAME_MJPEG */ \ + bFrameIndex, /* bFrameIndex : First (and only) frame descriptor */ \ + 0x00, /* bmCapabilities : Still images using capture method 0 are supported at this frame setting.D1: Fixed frame-rate. */ \ + WBVAL(wWidth), /* wWidth (2bytes): Width of frame is 128 pixels. */ \ + WBVAL(wHeight), /* wHeight (2bytes): Height of frame is 64 pixels. */ \ + DBVAL(dwMinBitRate), /* dwMinBitRate (4bytes): Min bit rate in bits/s */ \ + DBVAL(dwMaxBitRate), /* dwMaxBitRate (4bytes): Max bit rate in bits/s */ \ + DBVAL(dwMaxVideoFrameBufferSize), /* dwMaxVideoFrameBufSize (4bytes): Maximum video or still frame size, in bytes. */ \ + DBVAL(dwDefaultFrameInterval), /* dwDefaultFrameInterval : 1,000,000 * 100ns -> 10 FPS */ \ + 0x02, /* bFrameIntervalType : Indicates how the frame interval can be programmed. 0: Continuous frame interval 1..255: The number of discrete frame */ \ + DBVAL(dwMinFrameInterval1), /* dwMinFrameInterval : 1,000,000 ns *100ns -> 10 FPS,Shortest frame interval supported (at highest frame rate), in 100 ns units */ \ + DBVAL(dwMinFrameInterval2) /* dwMaxFrameInterval : 1,000,000 ns *100ns -> 10 FPS,Longest frame interval supported (at lowest frame rate), in 100 ns units */ +// clang-format on +#endif /* USB_VIDEO_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usbd_video.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usbd_video.c new file mode 100644 index 00000000..3adad164 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usbd_video.c @@ -0,0 +1,752 @@ +/** + * @file usbd_video.c + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbd_core.h" +#include "usbd_video.h" + +struct usbd_video_cfg_priv { + struct video_probe_and_commit_controls *probe; + struct video_probe_and_commit_controls *commit; + uint8_t power_mode; + uint8_t error_code; + uint8_t vcintf; + uint8_t vsintf; + usb_slist_t entity_info_list; +} usbd_video_cfg = { .vcintf = 0xff, .vsintf = 0xff }; + +static int usbd_video_control_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + uint8_t control_selector = (uint8_t)(setup->wValue >> 8); + + switch (control_selector) { + case VIDEO_VC_VIDEO_POWER_MODE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_SET_CUR: + break; + case VIDEO_REQUEST_GET_CUR: + break; + case VIDEO_REQUEST_GET_INFO: + break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + + break; + case VIDEO_VC_REQUEST_ERROR_CODE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: + (*data)[0] = 0x06; + *len = 1; + break; + case VIDEO_REQUEST_GET_INFO: + break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + + break; + default: + break; + } + + return 0; +} + +static int usbd_video_control_unit_terminal_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + uint8_t entity_id = (uint8_t)(setup->wIndex >> 8); + uint8_t control_selector = (uint8_t)(setup->wValue >> 8); + + usb_slist_t *i; + usb_slist_for_each(i, &usbd_video_cfg.entity_info_list) + { + struct video_entity_info *entity_info = usb_slist_entry(i, struct video_entity_info, list); + if (entity_info->bEntityId == entity_id) { + switch (entity_info->bDescriptorSubtype) { + case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE: + break; + case VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE: + if (entity_info->wTerminalType == VIDEO_ITT_CAMERA) { + switch (control_selector) { + case VIDEO_CT_AE_MODE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: + (*data)[0] = 0x08; + *len = 1; + break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: { + uint32_t dwExposureTimeAbsolute = 2500; + memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4); + *len = 4; + } break; + case VIDEO_REQUEST_GET_MIN: { + uint32_t dwExposureTimeAbsolute = 5; //0.0005sec + memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4); + *len = 4; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint32_t dwExposureTimeAbsolute = 2500; //0.2500sec + memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4); + *len = 4; + } break; + case VIDEO_REQUEST_GET_RES: { + uint32_t dwExposureTimeAbsolute = 5; //0.0005sec + memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4); + *len = 4; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint32_t dwExposureTimeAbsolute = 2500; //0.2500sec + memcpy(*data, (uint8_t *)&dwExposureTimeAbsolute, 4); + *len = 4; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_CT_FOCUS_ABSOLUTE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: { + uint16_t wFocusAbsolute = 0x0080; + memcpy(*data, (uint8_t *)&wFocusAbsolute, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MIN: { + uint16_t wFocusAbsolute = 0; + memcpy(*data, (uint8_t *)&wFocusAbsolute, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wFocusAbsolute = 0x00ff; + memcpy(*data, (uint8_t *)&wFocusAbsolute, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wFocusAbsolute = 0x0001; + memcpy(*data, (uint8_t *)&wFocusAbsolute, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wFocusAbsolute = 0x0080; + memcpy(*data, (uint8_t *)&wFocusAbsolute, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_CT_ZOOM_ABSOLUTE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: { + uint16_t wObjectiveFocalLength = 0x0064; + memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MIN: { + uint16_t wObjectiveFocalLength = 0x0064; + memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wObjectiveFocalLength = 0x00c8; + memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wObjectiveFocalLength = 0x0001; + memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wObjectiveFocalLength = 0x0064; + memcpy(*data, (uint8_t *)&wObjectiveFocalLength, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_CT_ROLL_ABSOLUTE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: { + uint16_t wRollAbsolute = 0x0000; + memcpy(*data, (uint8_t *)&wRollAbsolute, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MIN: { + uint16_t wRollAbsolute = 0x0000; + memcpy(*data, (uint8_t *)&wRollAbsolute, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wRollAbsolute = 0x00ff; + memcpy(*data, (uint8_t *)&wRollAbsolute, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wRollAbsolute = 0x0001; + memcpy(*data, (uint8_t *)&wRollAbsolute, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wRollAbsolute = 0x0000; + memcpy(*data, (uint8_t *)&wRollAbsolute, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_CT_FOCUS_AUTO_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: { + uint16_t wFocusAuto = 0x0000; + memcpy(*data, (uint8_t *)&wFocusAuto, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + default: + USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector); + return -1; + } + } else { + USB_LOG_WRN("Unhandled Video Class wTerminalType 0x%02x\r\n", entity_info->wTerminalType); + return -2; + } + break; + case VIDEO_VC_OUTPUT_TERMINAL_DESCRIPTOR_SUBTYPE: + break; + case VIDEO_VC_SELECTOR_UNIT_DESCRIPTOR_SUBTYPE: + break; + case VIDEO_VC_PROCESSING_UNIT_DESCRIPTOR_SUBTYPE: + switch (control_selector) { + case VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: { + uint16_t wBacklightCompensation = 0x0004; + memcpy(*data, (uint8_t *)&wBacklightCompensation, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MIN: { + uint16_t wBacklightCompensation = 0; + memcpy(*data, (uint8_t *)&wBacklightCompensation, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wBacklightCompensation = 8; + memcpy(*data, (uint8_t *)&wBacklightCompensation, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wBacklightCompensation = 1; + memcpy(*data, (uint8_t *)&wBacklightCompensation, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wBacklightCompensation = 4; + memcpy(*data, (uint8_t *)&wBacklightCompensation, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_PU_BRIGHTNESS_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_SET_CUR: { + uint16_t wBrightness = (uint16_t)(*data)[1] << 8 | (uint16_t)(*data)[0]; + USB_LOG_INFO("Video set brightness:%d\r\n", wBrightness); + } break; + case VIDEO_REQUEST_GET_CUR: { + uint16_t wBrightness = 0x0080; + memcpy(*data, (uint8_t *)&wBrightness, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MIN: { + uint16_t wBrightness = 0x0001; + memcpy(*data, (uint8_t *)&wBrightness, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wBrightness = 0x00ff; + memcpy(*data, (uint8_t *)&wBrightness, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wBrightness = 0x0001; + memcpy(*data, (uint8_t *)&wBrightness, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wBrightness = 0x0080; + memcpy(*data, (uint8_t *)&wBrightness, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_PU_CONTRAST_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: { + uint16_t wContrast = 0x0080; + memcpy(*data, (uint8_t *)&wContrast, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MIN: { + uint16_t wContrast = 0x0001; + memcpy(*data, (uint8_t *)&wContrast, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wContrast = 0x00ff; + memcpy(*data, (uint8_t *)&wContrast, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wContrast = 0x0001; + memcpy(*data, (uint8_t *)&wContrast, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wContrast = 0x0080; + memcpy(*data, (uint8_t *)&wContrast, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_PU_HUE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: { + uint16_t wHue = 0x0080; + memcpy(*data, (uint8_t *)&wHue, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MIN: { + uint16_t wHue = 0x0001; + memcpy(*data, (uint8_t *)&wHue, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wHue = 0x00ff; + memcpy(*data, (uint8_t *)&wHue, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wHue = 0x0001; + memcpy(*data, (uint8_t *)&wHue, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wHue = 0x0080; + memcpy(*data, (uint8_t *)&wHue, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_PU_SATURATION_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_MIN: { + uint16_t wSaturation = 0x0001; + memcpy(*data, (uint8_t *)&wSaturation, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wSaturation = 0x00ff; + memcpy(*data, (uint8_t *)&wSaturation, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wSaturation = 0x0001; + memcpy(*data, (uint8_t *)&wSaturation, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wSaturation = 0x0080; + memcpy(*data, (uint8_t *)&wSaturation, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_PU_SHARPNESS_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_MIN: { + uint16_t wSharpness = 0x0001; + memcpy(*data, (uint8_t *)&wSharpness, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wSharpness = 0x00ff; + memcpy(*data, (uint8_t *)&wSharpness, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wSharpness = 0x0001; + memcpy(*data, (uint8_t *)&wSharpness, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wSharpness = 0x0080; + memcpy(*data, (uint8_t *)&wSharpness, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_PU_GAIN_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_MIN: { + uint16_t wGain = 0; + memcpy(*data, (uint8_t *)&wGain, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wGain = 255; + memcpy(*data, (uint8_t *)&wGain, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wGain = 1; + memcpy(*data, (uint8_t *)&wGain, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wGain = 255; + memcpy(*data, (uint8_t *)&wGain, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: { + uint16_t wWhiteBalance_Temprature = 417; + memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MIN: { + uint16_t wWhiteBalance_Temprature = 300; + memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_MAX: { + uint16_t wWhiteBalance_Temprature = 600; + memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_RES: { + uint16_t wWhiteBalance_Temprature = 1; + memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2); + *len = 2; + } break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; //struct video_camera_capabilities + *len = 1; + break; + case VIDEO_REQUEST_GET_DEF: { + uint16_t wWhiteBalance_Temprature = 417; + memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature, 2); + *len = 2; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: { + uint16_t wWhiteBalance_Temprature_Auto = 1; + memcpy(*data, (uint8_t *)&wWhiteBalance_Temprature_Auto, 1); + *len = 1; + } break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + default: + usbd_video_cfg.error_code = 0x06; + USB_LOG_WRN("Unhandled Video Class control selector 0x%02x\r\n", control_selector); + return -1; + } + break; + case VIDEO_VC_EXTENSION_UNIT_DESCRIPTOR_SUBTYPE: + break; + case VIDEO_VC_ENCODING_UNIT_DESCRIPTOR_SUBTYPE: + break; + + default: + break; + } + } + } + return 0; +} + +static int usbd_video_stream_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + uint8_t control_selector = (uint8_t)(setup->wValue >> 8); + + switch (control_selector) { + case VIDEO_VS_PROBE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_SET_CUR: + //memcpy((uint8_t *)usbd_video_cfg.probe, *data, setup->wLength); + break; + case VIDEO_REQUEST_GET_CUR: + *data = (uint8_t *)usbd_video_cfg.probe; + *len = sizeof(struct video_probe_and_commit_controls); + break; + + case VIDEO_REQUEST_GET_MIN: + case VIDEO_REQUEST_GET_MAX: + case VIDEO_REQUEST_GET_RES: + case VIDEO_REQUEST_GET_DEF: + *data = (uint8_t *)usbd_video_cfg.probe; + *len = sizeof(struct video_probe_and_commit_controls); + break; + case VIDEO_REQUEST_GET_LEN: + (*data)[0] = sizeof(struct video_probe_and_commit_controls); + *len = 1; + break; + + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; + *len = 1; + break; + + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_VS_COMMIT_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_SET_CUR: + //memcpy((uint8_t *)usbd_video_cfg.commit, *data, setup->wLength); + break; + case VIDEO_REQUEST_GET_CUR: + *data = (uint8_t *)usbd_video_cfg.commit; + *len = sizeof(struct video_probe_and_commit_controls); + break; + case VIDEO_REQUEST_GET_MIN: + case VIDEO_REQUEST_GET_MAX: + case VIDEO_REQUEST_GET_RES: + case VIDEO_REQUEST_GET_DEF: + *data = (uint8_t *)usbd_video_cfg.commit; + *len = sizeof(struct video_probe_and_commit_controls); + break; + + case VIDEO_REQUEST_GET_LEN: + (*data)[0] = sizeof(struct video_probe_and_commit_controls); + *len = 1; + break; + + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x03; + *len = 1; + break; + + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + case VIDEO_VS_STREAM_ERROR_CODE_CONTROL: + switch (setup->bRequest) { + case VIDEO_REQUEST_GET_CUR: + *data = &usbd_video_cfg.error_code; + *len = 1; + break; + case VIDEO_REQUEST_GET_INFO: + (*data)[0] = 0x01; + *len = 1; + break; + default: + USB_LOG_WRN("Unhandled Video Class bRequest 0x%02x\r\n", setup->bRequest); + return -1; + } + break; + default: + break; + } + + return 0; +} + +static int video_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USB_LOG_DBG("Video Class request: " + "bRequest 0x%02x\r\n", + setup->bRequest); + + uint8_t intf_num = (uint8_t)setup->wIndex; + uint8_t entity_id = (uint8_t)(setup->wIndex >> 8); + + if (usbd_video_cfg.vcintf == intf_num) { /* Video Control Interface */ + if (entity_id == 0) { + return usbd_video_control_request_handler(setup, data, len); /* Interface Control Requests */ + } else { + return usbd_video_control_unit_terminal_request_handler(setup, data, len); /* Unit and Terminal Requests */ + } + } else if (usbd_video_cfg.vsintf == intf_num) { /* Video Stream Inteface */ + return usbd_video_stream_request_handler(setup, data, len); /* Interface Stream Requests */ + } + return -1; +} + +static void video_notify_handler(uint8_t event, void *arg) +{ + switch (event) { + case USBD_EVENT_RESET: + usbd_video_cfg.error_code = 0; + usbd_video_cfg.power_mode = 0; + break; + + case USBD_EVENT_SOF: + usbd_video_sof_callback(); + break; + + case USBD_EVENT_SET_INTERFACE: { + struct usb_interface_descriptor *intf = (struct usb_interface_descriptor *)arg; + usbd_video_set_interface_callback(intf->bAlternateSetting); + } + + break; + default: + break; + } +} + +void usbd_video_add_interface(usbd_class_t *class, usbd_interface_t *intf) +{ + static usbd_class_t *last_class = NULL; + + if (last_class != class) { + last_class = class; + usbd_class_register(class); + } + + intf->class_handler = video_class_request_handler; + intf->custom_handler = NULL; + intf->vendor_handler = NULL; + intf->notify_handler = video_notify_handler; + usbd_class_add_interface(class, intf); + + if (usbd_video_cfg.vcintf == 0xff) { + usbd_video_cfg.vcintf = intf->intf_num; + } else if (usbd_video_cfg.vsintf == 0xff) { + usbd_video_cfg.vsintf = intf->intf_num; + } +} + +void usbd_video_set_probe_and_commit_controls(struct video_probe_and_commit_controls *probe, + struct video_probe_and_commit_controls *commit) +{ + usbd_video_cfg.probe = probe; + usbd_video_cfg.commit = commit; +} + +void usbd_video_add_entity_info(struct video_entity_info *info) +{ + usb_slist_add_tail(&usbd_video_cfg.entity_info_list, &info->list); +} + +__WEAK void usbd_video_sof_callback(void) +{ +} \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usbd_video.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usbd_video.h new file mode 100644 index 00000000..b4693357 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/class/video/usbd_video.h @@ -0,0 +1,44 @@ +/** + * @file usbd_video.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBD_VIDEO_H_ +#define _USBD_VIDEO_H_ + +#include "usb_video.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void usbd_video_add_interface(usbd_class_t *class, usbd_interface_t *intf); + +void usbd_video_set_probe_and_commit_controls(struct video_probe_and_commit_controls *probe, + struct video_probe_and_commit_controls *commit); +void usbd_video_add_entity_info(struct video_entity_info *info); +void usbd_video_sof_callback(void); +void usbd_video_set_interface_callback(uint8_t value); + +#ifdef __cplusplus +} +#endif + +#endif /* USBD_VIDEO_H_ */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_dc.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_dc.h new file mode 100644 index 00000000..0b8ae7e7 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_dc.h @@ -0,0 +1,200 @@ +/** + * @file usb_dc.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USB_DC_H +#define _USB_DC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * USB endpoint direction and number. + */ +#define USB_EP_DIR_MASK 0x80U +#define USB_EP_DIR_IN 0x80U +#define USB_EP_DIR_OUT 0x00U + +/** Get endpoint index (number) from endpoint address */ +#define USB_EP_GET_IDX(ep) ((ep) & ~USB_EP_DIR_MASK) +/** Get direction from endpoint address */ +#define USB_EP_GET_DIR(ep) ((ep)&USB_EP_DIR_MASK) +/** Get endpoint address from endpoint index and direction */ +#define USB_EP_GET_ADDR(idx, dir) ((idx) | ((dir)&USB_EP_DIR_MASK)) +/** True if the endpoint is an IN endpoint */ +#define USB_EP_DIR_IS_IN(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_IN) +/** True if the endpoint is an OUT endpoint */ +#define USB_EP_DIR_IS_OUT(ep) (USB_EP_GET_DIR(ep) == USB_EP_DIR_OUT) + +/* Default USB control EP, always 0 and 0x80 */ +#define USB_CONTROL_OUT_EP0 0 +#define USB_CONTROL_IN_EP0 0x80 + +/**< maximum packet size (MPS) for EP 0 */ +#define USB_CTRL_EP_MPS 64 + +/** + * USB endpoint Transfer Type mask. + */ +#define USBD_EP_TYPE_CTRL 0 +#define USBD_EP_TYPE_ISOC 1 +#define USBD_EP_TYPE_BULK 2 +#define USBD_EP_TYPE_INTR 3 +#define USBD_EP_TYPE_MASK 3 + +/** + * @brief USB Endpoint Configuration. + * + * Structure containing the USB endpoint configuration. + */ +struct usbd_endpoint_cfg { + /** The number associated with the EP in the device + * configuration structure + * IN EP = 0x80 | \ + * OUT EP = 0x00 | \ + */ + uint8_t ep_addr; + /** Endpoint Transfer Type. + * May be Bulk, Interrupt, Control or Isochronous + */ + uint8_t ep_type; + /** Endpoint max packet size */ + uint16_t ep_mps; +}; + +/** + * @brief USB Device Core Layer API + * @defgroup _usb_device_core_api USB Device Core API + * @{ + */ + +/** + * @brief Set USB device address + * + * @param[in] addr Device address + * + * @return 0 on success, negative errno code on fail. + */ +int usbd_set_address(const uint8_t addr); + +/* + * @brief configure and enable endpoint + * + * This function sets endpoint configuration according to one specified in USB + * endpoint descriptor and then enables it for data transfers. + * + * @param [in] ep_desc Endpoint descriptor byte array + * + * @return true if successfully configured and enabled + */ +int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg); +/** + * @brief Disable the selected endpoint + * + * Function to disable the selected endpoint. Upon success interrupts are + * disabled for the corresponding endpoint and the endpoint is no longer able + * for transmitting/receiving data. + * + * @param[in] ep Endpoint address corresponding to the one + * listed in the device configuration table + * + * @return 0 on success, negative errno code on fail. + */ +int usbd_ep_close(const uint8_t ep); +/** + * @brief Set stall condition for the selected endpoint + * + * @param[in] ep Endpoint address corresponding to the one + * listed in the device configuration table + * + * @return 0 on success, negative errno code on fail. + */ +int usbd_ep_set_stall(const uint8_t ep); +/** + * @brief Clear stall condition for the selected endpoint + * + * @param[in] ep Endpoint address corresponding to the one + * listed in the device configuration table + * + * @return 0 on success, negative errno code on fail. + */ +int usbd_ep_clear_stall(const uint8_t ep); +/** + * @brief Check if the selected endpoint is stalled + * + * @param[in] ep Endpoint address corresponding to the one + * listed in the device configuration table + * @param[out] stalled Endpoint stall status + * + * @return 0 on success, negative errno code on fail. + */ +int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled); +/** + * @brief Write data to the specified endpoint + * + * This function is called to write data to the specified endpoint. The + * supplied usbd_endpoint_callback function will be called when data is transmitted + * out. + * + * @param[in] ep Endpoint address corresponding to the one + * listed in the device configuration table + * @param[in] data Pointer to data to write + * @param[in] data_len Length of the data requested to write. This may + * be zero for a zero length status packet. + * @param[out] ret_bytes Bytes scheduled for transmission. This value + * may be NULL if the application expects all + * bytes to be written + * + * @return 0 on success, negative errno code on fail. + */ +int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes); +/** + * @brief Read data from the specified endpoint + * + * This is similar to usb_dc_ep_read, the difference being that, it doesn't + * clear the endpoint NAKs so that the consumer is not bogged down by further + * upcalls till he is done with the processing of the data. The caller should + * reactivate ep by setting max_data_len 0 do so. + * + * @param[in] ep Endpoint address corresponding to the one + * listed in the device configuration table + * @param[in] data Pointer to data buffer to write to + * @param[in] max_data_len Max length of data to read + * @param[out] read_bytes Number of bytes read. If data is NULL and + * max_data_len is 0 the number of bytes + * available for read should be returned. + * + * @return 0 on success, negative errno code on fail. + */ +int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_def.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_def.h new file mode 100644 index 00000000..ae5a468f --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_def.h @@ -0,0 +1,671 @@ +/** + * @file usb_def.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef USB_DEF_H +#define USB_DEF_H + +/* Useful define */ +#define USB_1_1 0x0110 +#define USB_2_0 0x0200 +/* Set USB version to 2.1 so that the host will request the BOS descriptor */ +#define USB_2_1 0x0210 + +/* Device speeds */ +#define USB_SPEED_UNKNOWN 0 /* Transfer rate not yet set */ +#define USB_SPEED_LOW 1 /* USB 1.1 */ +#define USB_SPEED_FULL 2 /* USB 1.1 */ +#define USB_SPEED_HIGH 3 /* USB 2.0 */ +#define USB_SPEED_VARIABLE 4 /* Wireless USB 2.5 */ + +/* Maximum number of devices per controller */ +#define USB_MAX_DEVICES (127) + +// USB PID Types +#define USB_PID_OUT (0x01) /* Tokens */ +#define USB_PID_IN (0x09) +#define USB_PID_SOF (0x05) +#define USB_PID_SETUP (0x0d) + +#define USB_PID_DATA0 (0x03) /* Data */ +#define USB_PID_DATA1 (0x0b) +#define USB_PID_DATA2 (0x07) +#define USB_PID_MDATA (0x0f) + +#define USB_PID_ACK (0x02) /* Handshake */ +#define USB_PID_NAK (0x0a) +#define USB_PID_STALL (0x0e) +#define USB_PID_NYET (0x06) + +#define USB_PID_PRE (0x0c) /* Special */ +#define USB_PID_ERR (0x0c) +#define USB_PID_SPLIT (0x08) +#define USB_PID_PING (0x04) +#define USB_PID_RESERVED (0x00) + +#define USB_REQUEST_DIR_SHIFT 7U /* Bits 7: Request dir */ +#define USB_REQUEST_DIR_OUT (0U << USB_REQUEST_DIR_SHIFT) /* Bit 7=0: Host-to-device */ +#define USB_REQUEST_DIR_IN (1U << USB_REQUEST_DIR_SHIFT) /* Bit 7=1: Device-to-host */ +#define USB_REQUEST_DIR_MASK (1U << USB_REQUEST_DIR_SHIFT) /* Bit 7=1: Direction bit */ + +#define USB_REQUEST_TYPE_SHIFT 5U /* Bits 5:6: Request type */ +#define USB_REQUEST_STANDARD (0U << USB_REQUEST_TYPE_SHIFT) +#define USB_REQUEST_CLASS (1U << USB_REQUEST_TYPE_SHIFT) +#define USB_REQUEST_VENDOR (2U << USB_REQUEST_TYPE_SHIFT) +#define USB_REQUEST_RESERVED (3U << USB_REQUEST_TYPE_SHIFT) +#define USB_REQUEST_TYPE_MASK (3U << USB_REQUEST_TYPE_SHIFT) + +#define USB_REQUEST_RECIPIENT_SHIFT 0U /* Bits 0:4: Recipient */ +#define USB_REQUEST_RECIPIENT_DEVICE (0U << USB_REQUEST_RECIPIENT_SHIFT) +#define USB_REQUEST_RECIPIENT_INTERFACE (1U << USB_REQUEST_RECIPIENT_SHIFT) +#define USB_REQUEST_RECIPIENT_ENDPOINT (2U << USB_REQUEST_RECIPIENT_SHIFT) +#define USB_REQUEST_RECIPIENT_OTHER (3U << USB_REQUEST_RECIPIENT_SHIFT) +#define USB_REQUEST_RECIPIENT_MASK (3U << USB_REQUEST_RECIPIENT_SHIFT) + +/* USB Standard Request Codes */ +#define USB_REQUEST_GET_STATUS 0x00 +#define USB_REQUEST_CLEAR_FEATURE 0x01 +#define USB_REQUEST_SET_FEATURE 0x03 +#define USB_REQUEST_SET_ADDRESS 0x05 +#define USB_REQUEST_GET_DESCRIPTOR 0x06 +#define USB_REQUEST_SET_DESCRIPTOR 0x07 +#define USB_REQUEST_GET_CONFIGURATION 0x08 +#define USB_REQUEST_SET_CONFIGURATION 0x09 +#define USB_REQUEST_GET_INTERFACE 0x0A +#define USB_REQUEST_SET_INTERFACE 0x0B +#define USB_REQUEST_SYNCH_FRAME 0x0C +#define USB_REQUEST_SET_ENCRYPTION 0x0D +#define USB_REQUEST_GET_ENCRYPTION 0x0E +#define USB_REQUEST_RPIPE_ABORT 0x0E +#define USB_REQUEST_SET_HANDSHAKE 0x0F +#define USB_REQUEST_RPIPE_RESET 0x0F +#define USB_REQUEST_GET_HANDSHAKE 0x10 +#define USB_REQUEST_SET_CONNECTION 0x11 +#define USB_REQUEST_SET_SECURITY_DATA 0x12 +#define USB_REQUEST_GET_SECURITY_DATA 0x13 +#define USB_REQUEST_SET_WUSB_DATA 0x14 +#define USB_REQUEST_LOOPBACK_DATA_WRITE 0x15 +#define USB_REQUEST_LOOPBACK_DATA_READ 0x16 +#define USB_REQUEST_SET_INTERFACE_DS 0x17 + +/* USB Standard Feature selectors */ +#define USB_FEATURE_ENDPOINT_HALT 0 +#define USB_FEATURE_SELF_POWERED 0 +#define USB_FEATURE_REMOTE_WAKEUP 1 +#define USB_FEATURE_TEST_MODE 2 +#define USB_FEATURE_BATTERY 2 +#define USB_FEATURE_BHNPENABLE 3 +#define USB_FEATURE_WUSBDEVICE 3 +#define USB_FEATURE_AHNPSUPPORT 4 +#define USB_FEATURE_AALTHNPSUPPORT 5 +#define USB_FEATURE_DEBUGMODE 6 + +/* USB GET_STATUS Bit Values */ +#define USB_GETSTATUS_ENDPOINT_HALT 0x01 +#define USB_GETSTATUS_SELF_POWERED 0x01 +#define USB_GETSTATUS_REMOTE_WAKEUP 0x02 + +/* USB Descriptor Types */ +#define USB_DESCRIPTOR_TYPE_DEVICE 0x01U +#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02U +#define USB_DESCRIPTOR_TYPE_STRING 0x03U +#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04U +#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05U +#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06U +#define USB_DESCRIPTOR_TYPE_OTHER_SPEED 0x07U +#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08U +#define USB_DESCRIPTOR_TYPE_OTG 0x09U +#define USB_DESCRIPTOR_TYPE_DEBUG 0x0AU +#define USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0BU +#define USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE 0x0FU +#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 0x10U +#define USB_DESCRIPTOR_TYPE_WIRELESS_ENDPOINTCOMP 0x11U + +/* Class Specific Descriptor */ +#define USB_CS_DESCRIPTOR_TYPE_DEVICE 0x21U +#define USB_CS_DESCRIPTOR_TYPE_CONFIGURATION 0x22U +#define USB_CS_DESCRIPTOR_TYPE_STRING 0x23U +#define USB_CS_DESCRIPTOR_TYPE_INTERFACE 0x24U +#define USB_CS_DESCRIPTOR_TYPE_ENDPOINT 0x25U + +#define USB_DESCRIPTOR_TYPE_SUPERSPEED_ENDPOINT_COMPANION 0x30U +#define USB_DESCRIPTOR_TYPE_SUPERSPEED_ISO_ENDPOINT_COMPANION 0x31U + +/* USB Device Classes */ +#define USB_DEVICE_CLASS_RESERVED 0x00 +#define USB_DEVICE_CLASS_AUDIO 0x01 +#define USB_DEVICE_CLASS_CDC 0x02 +#define USB_DEVICE_CLASS_HID 0x03 +#define USB_DEVICE_CLASS_MONITOR 0x04 +#define USB_DEVICE_CLASS_PHYSICAL 0x05 +#define USB_DEVICE_CLASS_IMAGE 0x06 +#define USB_DEVICE_CLASS_PRINTER 0x07 +#define USB_DEVICE_CLASS_MASS_STORAGE 0x08 +#define USB_DEVICE_CLASS_HUB 0x09 +#define USB_DEVICE_CLASS_CDC_DATA 0x0a +#define USB_DEVICE_CLASS_SMART_CARD 0x0b +#define USB_DEVICE_CLASS_SECURITY 0x0d +#define USB_DEVICE_CLASS_VIDEO 0x0e +#define USB_DEVICE_CLASS_HEALTHCARE 0x0f +#define USB_DEVICE_CLASS_DIAG_DEVICE 0xdc +#define USB_DEVICE_CLASS_WIRELESS 0xe0 +#define USB_DEVICE_CLASS_MISC 0xef +#define USB_DEVICE_CLASS_APP_SPECIFIC 0xfe +#define USB_DEVICE_CLASS_VEND_SPECIFIC 0xff + +/* usb string index define */ +#define USB_STRING_LANGID_INDEX 0x00 +#define USB_STRING_MFC_INDEX 0x01 +#define USB_STRING_PRODUCT_INDEX 0x02 +#define USB_STRING_SERIAL_INDEX 0x03 +#define USB_STRING_CONFIG_INDEX 0x04 +#define USB_STRING_INTERFACE_INDEX 0x05 +#define USB_STRING_OS_INDEX 0x06 +#define USB_STRING_MAX USB_STRING_OS_INDEX +/* + * Devices supporting Microsoft OS Descriptors store special string + * descriptor at fixed index (0xEE). It is read when a new device is + * attached to a computer for the first time. + */ +#define USB_OSDESC_STRING_DESC_INDEX 0xEE + +/* bmAttributes in Configuration Descriptor */ +#define USB_CONFIG_REMOTE_WAKEUP 0x20 +#define USB_CONFIG_POWERED_MASK 0x40 +#define USB_CONFIG_BUS_POWERED 0x80 +#define USB_CONFIG_SELF_POWERED 0xC0 + +/* bMaxPower in Configuration Descriptor */ +#define USB_CONFIG_POWER_MA(mA) ((mA) / 2) + +/* bEndpointAddress in Endpoint Descriptor */ +#define USB_ENDPOINT_DIRECTION_MASK 0x80 +#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00) +#define USB_ENDPOINT_IN(addr) ((addr) | 0x80) + +/* bmAttributes in Endpoint Descriptor */ +#define USB_ENDPOINT_TYPE_SHIFT 0 +#define USB_ENDPOINT_TYPE_CONTROL (0 << USB_ENDPOINT_TYPE_SHIFT) +#define USB_ENDPOINT_TYPE_ISOCHRONOUS (1 << USB_ENDPOINT_TYPE_SHIFT) +#define USB_ENDPOINT_TYPE_BULK (2 << USB_ENDPOINT_TYPE_SHIFT) +#define USB_ENDPOINT_TYPE_INTERRUPT (3 << USB_ENDPOINT_TYPE_SHIFT) +#define USB_ENDPOINT_TYPE_MASK (3 << USB_ENDPOINT_TYPE_SHIFT) + +#define USB_ENDPOINT_SYNC_SHIFT 2 +#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION (0 << USB_ENDPOINT_SYNC_SHIFT) +#define USB_ENDPOINT_SYNC_ASYNCHRONOUS (1 << USB_ENDPOINT_SYNC_SHIFT) +#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << USB_ENDPOINT_SYNC_SHIFT) +#define USB_ENDPOINT_SYNC_SYNCHRONOUS (3 << USB_ENDPOINT_SYNC_SHIFT) +#define USB_ENDPOINT_SYNC_MASK (3 << USB_ENDPOINT_SYNC_SHIFT) + +#define USB_ENDPOINT_USAGE_SHIFT 4 +#define USB_ENDPOINT_USAGE_DATA (0 << USB_ENDPOINT_USAGE_SHIFT) +#define USB_ENDPOINT_USAGE_FEEDBACK (1 << USB_ENDPOINT_USAGE_SHIFT) +#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK (2 << USB_ENDPOINT_USAGE_SHIFT) +#define USB_ENDPOINT_USAGE_MASK (3 << USB_ENDPOINT_USAGE_SHIFT) + +#define USB_ENDPOINT_MAX_ADJUSTABLE (1 << 7) + +/* bDevCapabilityType in Device Capability Descriptor */ +#define USB_DEVICE_CAPABILITY_WIRELESS_USB 1 +#define USB_DEVICE_CAPABILITY_USB_2_0_EXTENSION 2 +#define USB_DEVICE_CAPABILITY_SUPERSPEED_USB 3 +#define USB_DEVICE_CAPABILITY_CONTAINER_ID 4 +#define USB_DEVICE_CAPABILITY_PLATFORM 5 +#define USB_DEVICE_CAPABILITY_POWER_DELIVERY_CAPABILITY 6 +#define USB_DEVICE_CAPABILITY_BATTERY_INFO_CAPABILITY 7 +#define USB_DEVICE_CAPABILITY_PD_CONSUMER_PORT_CAPABILITY 8 +#define USB_DEVICE_CAPABILITY_PD_PROVIDER_PORT_CAPABILITY 9 +#define USB_DEVICE_CAPABILITY_SUPERSPEED_PLUS 10 +#define USB_DEVICE_CAPABILITY_PRECISION_TIME_MEASUREMENT 11 +#define USB_DEVICE_CAPABILITY_WIRELESS_USB_EXT 12 + +#define USB_BOS_CAPABILITY_EXTENSION 0x02 +#define USB_BOS_CAPABILITY_PLATFORM 0x05 + +/* OTG SET FEATURE Constants */ +#define USB_OTG_FEATURE_B_HNP_ENABLE 3 /* Enable B device to perform HNP */ +#define USB_OTG_FEATURE_A_HNP_SUPPORT 4 /* A device supports HNP */ +#define USB_OTG_FEATURE_A_ALT_HNP_SUPPORT 5 /* Another port on the A device supports HNP */ + +/* WinUSB Microsoft OS 2.0 descriptor request codes */ +#define WINUSB_REQUEST_GET_DESCRIPTOR_SET 0x07 +#define WINUSB_REQUEST_SET_ALT_ENUM 0x08 + +/* WinUSB Microsoft OS 2.0 descriptor sizes */ +#define WINUSB_DESCRIPTOR_SET_HEADER_SIZE 10 +#define WINUSB_FUNCTION_SUBSET_HEADER_SIZE 8 +#define WINUSB_FEATURE_COMPATIBLE_ID_SIZE 20 + +/* WinUSB Microsoft OS 2.0 Descriptor Types */ +#define WINUSB_SET_HEADER_DESCRIPTOR_TYPE 0x00 +#define WINUSB_SUBSET_HEADER_CONFIGURATION_TYPE 0x01 +#define WINUSB_SUBSET_HEADER_FUNCTION_TYPE 0x02 +#define WINUSB_FEATURE_COMPATIBLE_ID_TYPE 0x03 +#define WINUSB_FEATURE_REG_PROPERTY_TYPE 0x04 +#define WINUSB_FEATURE_MIN_RESUME_TIME_TYPE 0x05 +#define WINUSB_FEATURE_MODEL_ID_TYPE 0x06 +#define WINUSB_FEATURE_CCGP_DEVICE_TYPE 0x07 + +#define WINUSB_PROP_DATA_TYPE_REG_SZ 0x01 +#define WINUSB_PROP_DATA_TYPE_REG_MULTI_SZ 0x07 + +/* WebUSB Descriptor Types */ +#define WEBUSB_DESCRIPTOR_SET_HEADER_TYPE 0x00 +#define WEBUSB_CONFIGURATION_SUBSET_HEADER_TYPE 0x01 +#define WEBUSB_FUNCTION_SUBSET_HEADER_TYPE 0x02 +#define WEBUSB_URL_TYPE 0x03 + +/* WebUSB Request Codes */ +#define WEBUSB_REQUEST_GET_URL 0x02 + +/* bScheme in URL descriptor */ +#define WEBUSB_URL_SCHEME_HTTP 0x00 +#define WEBUSB_URL_SCHEME_HTTPS 0x01 + +/* WebUSB Descriptor sizes */ +#define WEBUSB_DESCRIPTOR_SET_HEADER_SIZE 5 +#define WEBUSB_CONFIGURATION_SUBSET_HEADER_SIZE 4 +#define WEBUSB_FUNCTION_SUBSET_HEADER_SIZE 3 + +/* Setup packet definition used to read raw data from USB line */ +struct usb_setup_packet { + /** Request type. Bits 0:4 determine recipient, see + * \ref usb_request_recipient. Bits 5:6 determine type, see + * \ref usb_request_type. Bit 7 determines data transfer direction, see + * \ref usb_endpoint_direction. + */ + uint8_t bmRequestType; + + /** Request. If the type bits of bmRequestType are equal to + * \ref usb_request_type::LIBUSB_REQUEST_TYPE_STANDARD + * "USB_REQUEST_TYPE_STANDARD" then this field refers to + * \ref usb_standard_request. For other cases, use of this field is + * application-specific. */ + uint8_t bRequest; + + /** Value. Varies according to request */ + uint16_t wValue; + + /** Index. Varies according to request, typically used to pass an index + * or offset */ + uint16_t wIndex; + + /** Number of bytes to transfer */ + uint16_t wLength; +} __PACKED; + +#define USB_SIZEOF_SETUP_PACKET 8 + +/** Standard Device Descriptor */ +struct usb_device_descriptor { + uint8_t bLength; /* Descriptor size in bytes = 18 */ + uint8_t bDescriptorType; /* DEVICE descriptor type = 1 */ + uint16_t bcdUSB; /* USB spec in BCD, e.g. 0x0200 */ + uint8_t bDeviceClass; /* Class code, if 0 see interface */ + uint8_t bDeviceSubClass; /* Sub-Class code, 0 if class = 0 */ + uint8_t bDeviceProtocol; /* Protocol, if 0 see interface */ + uint8_t bMaxPacketSize0; /* Endpoint 0 max. size */ + uint16_t idVendor; /* Vendor ID per USB-IF */ + uint16_t idProduct; /* Product ID per manufacturer */ + uint16_t bcdDevice; /* Device release # in BCD */ + uint8_t iManufacturer; /* Index to manufacturer string */ + uint8_t iProduct; /* Index to product string */ + uint8_t iSerialNumber; /* Index to serial number string */ + uint8_t bNumConfigurations; /* Number of possible configurations */ +} __PACKED; + +#define USB_SIZEOF_DEVICE_DESC 18 + +/** Standard Configuration Descriptor */ +struct usb_configuration_descriptor { + uint8_t bLength; /* Descriptor size in bytes = 9 */ + uint8_t bDescriptorType; /* CONFIGURATION type = 2 or 7 */ + uint16_t wTotalLength; /* Length of concatenated descriptors */ + uint8_t bNumInterfaces; /* Number of interfaces, this config. */ + uint8_t bConfigurationValue; /* Value to set this config. */ + uint8_t iConfiguration; /* Index to configuration string */ + uint8_t bmAttributes; /* Config. characteristics */ + uint8_t bMaxPower; /* Max.power from bus, 2mA units */ +} __PACKED; + +#define USB_SIZEOF_CONFIG_DESC 9 + +/** Standard Interface Descriptor */ +struct usb_interface_descriptor { + uint8_t bLength; /* Descriptor size in bytes = 9 */ + uint8_t bDescriptorType; /* INTERFACE descriptor type = 4 */ + uint8_t bInterfaceNumber; /* Interface no.*/ + uint8_t bAlternateSetting; /* Value to select this IF */ + uint8_t bNumEndpoints; /* Number of endpoints excluding 0 */ + uint8_t bInterfaceClass; /* Class code, 0xFF = vendor */ + uint8_t bInterfaceSubClass; /* Sub-Class code, 0 if class = 0 */ + uint8_t bInterfaceProtocol; /* Protocol, 0xFF = vendor */ + uint8_t iInterface; /* Index to interface string */ +} __PACKED; + +#define USB_SIZEOF_INTERFACE_DESC 9 + +/** Standard Endpoint Descriptor */ +struct usb_endpoint_descriptor { + uint8_t bLength; /* Descriptor size in bytes = 7 */ + uint8_t bDescriptorType; /* ENDPOINT descriptor type = 5 */ + uint8_t bEndpointAddress; /* Endpoint # 0 - 15 | IN/OUT */ + uint8_t bmAttributes; /* Transfer type */ + uint16_t wMaxPacketSize; /* Bits 10:0 = max. packet size */ + uint8_t bInterval; /* Polling interval in (micro) frames */ +} __PACKED; + +#define USB_SIZEOF_ENDPOINT_DESC 7 + +/** Unicode (UTF16LE) String Descriptor */ +struct usb_string_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bString; +} __PACKED; + +#define USB_SIZEOF_STRING_LANGID_DESC 4 + +/* USB Interface Association Descriptor */ +struct usb_interface_association_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bFirstInterface; + uint8_t bInterfaceCount; + uint8_t bFunctionClass; + uint8_t bFunctionSubClass; + uint8_t bFunctionProtocol; + uint8_t iFunction; +} __PACKED; + +#define USB_SIZEOF_IAD_DESC 8 + +/** USB device_qualifier descriptor */ +struct usb_device_qualifier_descriptor { + uint8_t bLength; /* Descriptor size in bytes = 10 */ + uint8_t bDescriptorType; /* DEVICE QUALIFIER type = 6 */ + uint16_t bcdUSB; /* USB spec in BCD, e.g. 0x0200 */ + uint8_t bDeviceClass; /* Class code, if 0 see interface */ + uint8_t bDeviceSubClass; /* Sub-Class code, 0 if class = 0 */ + uint8_t bDeviceProtocol; /* Protocol, if 0 see interface */ + uint8_t bMaxPacketSize; /* Endpoint 0 max. size */ + uint8_t bNumConfigurations; /* Number of possible configurations */ + uint8_t bReserved; /* Reserved = 0 */ +} __PACKED; + +#define USB_SIZEOF_DEVICE_QUALIFIER_DESC 10 + +/* Microsoft OS function descriptor. + * This can be used to request a specific driver (such as WINUSB) to be + * loaded on Windows. Unlike other descriptors, it is requested by a special + * request USB_REQ_GETMSFTOSDESCRIPTOR. + * More details: + * https://msdn.microsoft.com/en-us/windows/hardware/gg463179 + * And excellent explanation: + * https://github.com/pbatard/libwdi/wiki/WCID-Devices + * + * The device will have exactly one "Extended Compat ID Feature Descriptor", + * which may contain multiple "Function Descriptors" associated with + * different interfaces. + */ + +/* MS OS 1.0 string descriptor */ +struct usb_msosv1_string_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bString[14]; + uint8_t bMS_VendorCode; /* Vendor Code, used for a control request */ + uint8_t bPad; /* Padding byte for VendorCode look as UTF16 */ +} __PACKED; + +/* MS OS 1.0 Header descriptor */ +struct usb_msosv1_compat_id_header_descriptor { + uint32_t dwLength; + uint16_t bcdVersion; + uint16_t wIndex; + uint8_t bCount; + uint8_t reserved[7]; +} __PACKED; + +/* MS OS 1.0 Function descriptor */ +struct usb_msosv1_comp_id_function_descriptor { + uint8_t bFirstInterfaceNumber; + uint8_t reserved1; + uint8_t compatibleID[8]; + uint8_t subCompatibleID[8]; + uint8_t reserved2[6]; +} __PACKED; + +#define usb_msosv1_comp_id_create(x) \ + struct usb_msosv1_comp_id { \ + struct usb_msosv1_compat_id_header_descriptor compat_id_header; \ + struct usb_msosv1_comp_id_function_descriptor compat_id_function[x]; \ + }; + +struct usb_msosv1_descriptor { + uint8_t *string; + uint8_t string_len; + uint8_t vendor_code; + uint8_t *compat_id; + uint16_t compat_id_len; + uint8_t *comp_id_property; + uint16_t comp_id_property_len; +}; + +/* MS OS 2.0 Header descriptor */ +struct usb_msosv2_header_descriptor { + uint32_t dwLength; + uint16_t bcdVersion; + uint16_t wIndex; + uint8_t bCount; +} __PACKED; + +/*Microsoft OS 2.0 set header descriptor*/ +struct usb_msosv2_set_header_descriptor { + uint16_t wLength; + uint16_t wDescriptorType; + uint32_t dwWindowsVersion; + uint16_t wDescriptorSetTotalLength; +} __PACKED; + +/* Microsoft OS 2.0 compatibleID descriptor*/ +struct usb_msosv2_comp_id_descriptor { + uint16_t wLength; + uint16_t wDescriptorType; + uint8_t compatibleID[8]; + uint8_t subCompatibleID[8]; +} __PACKED; + +/* MS OS 2.0 property descriptor */ +struct usb_msosv2_property_descriptor { + uint16_t wLength; + uint16_t wDescriptorType; + uint32_t dwPropertyDataType; + uint16_t wPropertyNameLength; + const char *bPropertyName; + uint32_t dwPropertyDataLength; + const char *bPropertyData; +}; + +/* Microsoft OS 2.0 subset function descriptor */ +struct usb_msosv2_subset_function_descriptor { + uint16_t wLength; + uint16_t wDescriptorType; + uint8_t bFirstInterface; + uint8_t bReserved; + uint16_t wSubsetLength; +} __PACKED; + +struct usb_msosv2_descriptor { + uint8_t *compat_id; + uint16_t compat_id_len; + uint8_t vendor_code; +}; + +/* BOS header Descriptor */ +struct usb_bos_header_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumDeviceCaps; +} __PACKED; + +/* BOS Capability platform Descriptor */ +struct usb_bos_capability_platform_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint8_t bReserved; + uint8_t PlatformCapabilityUUID[16]; +} __PACKED; + +/* BOS Capability MS OS Descriptors version 2 */ +struct usb_bos_capability_msosv2_descriptor { + uint32_t dwWindowsVersion; + uint16_t wMSOSDescriptorSetTotalLength; + uint8_t bVendorCode; + uint8_t bAltEnumCode; +} __PACKED; + +/* BOS Capability webusb */ +struct usb_bos_capability_webusb_descriptor { + uint16_t bcdVersion; + uint8_t bVendorCode; + uint8_t iLandingPage; +} __PACKED; + +/* BOS Capability extension Descriptor*/ +struct usb_bos_capability_extension_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint32_t bmAttributes; +} __PACKED; + +/* Microsoft OS 2.0 Platform Capability Descriptor +* See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/ +* microsoft-defined-usb-descriptors +* Adapted from the source: +* https://github.com/sowbug/weblight/blob/master/firmware/webusb.c +* (BSD-2) Thanks http://janaxelson.com/files/ms_os_20_descriptors.c +*/ +struct usb_bos_capability_platform_msosv2_descriptor { + struct usb_bos_capability_platform_descriptor platform_msos; + struct usb_bos_capability_msosv2_descriptor data_msosv2; +} __PACKED; + +/* WebUSB Platform Capability Descriptor: +* https://wicg.github.io/webusb/#webusb-platform-capability-descriptor +*/ +struct usb_bos_capability_platform_webusb_descriptor { + struct usb_bos_capability_platform_descriptor platform_webusb; + struct usb_bos_capability_webusb_descriptor data_webusb; +} __PACKED; + +struct usb_webusb_url_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bScheme; + char URL[]; +} __PACKED; + +struct usb_bos_descriptor { + uint8_t *string; + uint32_t string_len; +}; + +/* USB Device Capability Descriptor */ +struct usb_device_capability_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; +} __PACKED; + +/** USB descriptor header */ +struct usb_desc_header { + uint8_t bLength; /**< descriptor length */ + uint8_t bDescriptorType; /**< descriptor type */ +}; +// clang-format off +#define USB_DEVICE_DESCRIPTOR_INIT(bcdUSB, bDeviceClass, bDeviceSubClass, bDeviceProtocol, idVendor, idProduct, bcdDevice, bNumConfigurations) \ + 0x12, /* bLength */ \ + USB_DESCRIPTOR_TYPE_DEVICE, /* bDescriptorType */ \ + WBVAL(bcdUSB), /* bcdUSB */ \ + bDeviceClass, /* bDeviceClass */ \ + bDeviceSubClass, /* bDeviceSubClass */ \ + bDeviceProtocol, /* bDeviceProtocol */ \ + 0x40, /* bMaxPacketSize */ \ + WBVAL(idVendor), /* idVendor */ \ + WBVAL(idProduct), /* idProduct */ \ + WBVAL(bcdDevice), /* bcdDevice */ \ + USB_STRING_MFC_INDEX, /* iManufacturer */ \ + USB_STRING_PRODUCT_INDEX, /* iProduct */ \ + USB_STRING_SERIAL_INDEX, /* iSerial */ \ + bNumConfigurations /* bNumConfigurations */ + +#define USB_CONFIG_DESCRIPTOR_INIT(wTotalLength, bNumInterfaces, bConfigurationValue, bmAttributes, bMaxPower) \ + 0x09, /* bLength */ \ + USB_DESCRIPTOR_TYPE_CONFIGURATION, /* bDescriptorType */ \ + WBVAL(wTotalLength), /* wTotalLength */ \ + bNumInterfaces, /* bNumInterfaces */ \ + bConfigurationValue, /* bConfigurationValue */ \ + 0x00, /* iConfiguration */ \ + bmAttributes, /* bmAttributes */ \ + USB_CONFIG_POWER_MA(bMaxPower) /* bMaxPower */ + +#define USB_INTERFACE_DESCRIPTOR_INIT(bInterfaceNumber, bAlternateSetting, bNumEndpoints, \ + bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface) \ + 0x09, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE, /* bDescriptorType */ \ + bInterfaceNumber, /* bInterfaceNumber */ \ + bAlternateSetting, /* bAlternateSetting */ \ + bNumEndpoints, /* bNumEndpoints */ \ + bInterfaceClass, /* bInterfaceClass */ \ + bInterfaceSubClass, /* bInterfaceSubClass */ \ + bInterfaceProtocol, /* bInterfaceProtocol */ \ + iInterface /* iInterface */ + +#define USB_ENDPOINT_DESCRIPTOR_INIT(bEndpointAddress, bmAttributes, wMaxPacketSize, bInterval) \ + 0x07, /* bLength */ \ + USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType */ \ + bEndpointAddress, /* bEndpointAddress */ \ + bmAttributes, /* bmAttributes */ \ + WBVAL(wMaxPacketSize), /* wMaxPacketSize */ \ + bInterval /* bInterval */ + +#define USB_IAD_INIT(bFirstInterface, bInterfaceCount, bFunctionClass, bFunctionSubClass, bFunctionProtocol) \ + 0x08, /* bLength */ \ + USB_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, /* bDescriptorType */ \ + bFirstInterface, /* bFirstInterface */ \ + bInterfaceCount, /* bInterfaceCount */ \ + bFunctionClass, /* bFunctionClass */ \ + bFunctionSubClass, /* bFunctionSubClass */ \ + bFunctionProtocol, /* bFunctionProtocol */ \ + 0x00 /* iFunction */ + +#define USB_LANGID_INIT(id) \ + 0x04, /* bLength */ \ + USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ \ + WBVAL(id) /* wLangID0 */ +// clang-format on + +#endif diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_errno.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_errno.h new file mode 100644 index 00000000..7ccadb6c --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_errno.h @@ -0,0 +1,340 @@ +/**************************************************************************** + * include/errno.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_ERRNO_H +#define __INCLUDE_ERRNO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Convenience/compatibility definition. If the errno is accessed from the + * internal OS code, then the OS code should use the set_errno() and + * get_errno(). Currently, those are just placeholders but would be needed + * in the KERNEL mode build in order to instantiate the process address + * environment as necessary to access the TLS-based errno variable. + */ + +#define errno *__errno() +#define set_errno(e) \ + do \ + { \ + errno = (int)(e); \ + } \ + while (0) +#define get_errno() errno + +/* Definitions of error numbers and the string that would be + * returned by strerror(). + */ + +#define EPERM 1 +#define EPERM_STR "Operation not permitted" +#define ENOENT 2 +#define ENOENT_STR "No such file or directory" +#define ESRCH 3 +#define ESRCH_STR "No such process" +#define EINTR 4 +#define EINTR_STR "Interrupted system call" +#define EIO 5 +#define EIO_STR "I/O error" +#define ENXIO 6 +#define ENXIO_STR "No such device or address" +#define E2BIG 7 +#define E2BIG_STR "Arg list too long" +#define ENOEXEC 8 +#define ENOEXEC_STR "Exec format error" +#define EBADF 9 +#define EBADF_STR "Bad file number" +#define ECHILD 10 +#define ECHILD_STR "No child processes" +#define EAGAIN 11 +#define EWOULDBLOCK EAGAIN +#define EAGAIN_STR "Try again" +#define ENOMEM 12 +#define ENOMEM_STR "Out of memory" +#define EACCES 13 +#define EACCES_STR "Permission denied" +#define EFAULT 14 /* Linux errno extension */ +#define EFAULT_STR "Bad address" +#define ENOTBLK 15 +#define ENOTBLK_STR "Block device required" +#define EBUSY 16 +#define EBUSY_STR "Device or resource busy" +#define EEXIST 17 +#define EEXIST_STR "File exists" +#define EXDEV 18 +#define EXDEV_STR "Cross-device link" +#define ENODEV 19 +#define ENODEV_STR "No such device" +#define ENOTDIR 20 +#define ENOTDIR_STR "Not a directory" +#define EISDIR 21 +#define EISDIR_STR "Is a directory" +#define EINVAL 22 +#define EINVAL_STR "Invalid argument" +#define ENFILE 23 +#define ENFILE_STR "File table overflow" +#define EMFILE 24 +#define EMFILE_STR "Too many open files" +#define ENOTTY 25 +#define ENOTTY_STR "Not a typewriter" +#define ETXTBSY 26 +#define ETXTBSY_STR "Text file busy" +#define EFBIG 27 +#define EFBIG_STR "File too large" +#define ENOSPC 28 +#define ENOSPC_STR "No space left on device" +#define ESPIPE 29 +#define ESPIPE_STR "Illegal seek" +#define EROFS 30 +#define EROFS_STR "Read-only file system" +#define EMLINK 31 +#define EMLINK_STR "Too many links" +#define EPIPE 32 +#define EPIPE_STR "Broken pipe" +#define EDOM 33 +#define EDOM_STR "Math argument out of domain of func" +#define ERANGE 34 +#define ERANGE_STR "Math result not representable" +#define ENOMSG 35 +#define ENOMSG_STR "No message of desired type" +#define EIDRM 36 +#define EIDRM_STR "Identifier removed" +#define ECHRNG 37 /* Linux errno extension */ +#define ECHRNG_STR "Channel number out of range" +#define EL2NSYNC 38 /* Linux errno extension */ +#define EL2NSYNC_STR "Level 2 not synchronized" +#define EL3HLT 39 /* Linux errno extension */ +#define EL3HLT_STR "Level 3 halted" +#define EL3RST 40 /* Linux errno extension */ +#define EL3RST_STR "Level 3 reset" +#define ELNRNG 41 /* Linux errno extension */ +#define ELNRNG_STR "Link number out of range" +#define EUNATCH 42 /* Linux errno extension */ +#define EUNATCH_STR "Protocol driver not attached" +#define ENOCSI 43 /* Linux errno extension */ +#define ENOCSI_STR "No CSI structure available" +#define EL2HLT 44 /* Linux errno extension */ +#define EL2HLT_STR "Level 2 halted" +#define EDEADLK 45 +#define EDEADLK_STR "Resource deadlock would occur" +#define ENOLCK 46 +#define ENOLCK_STR "No record locks available" + +#define EBADE 50 /* Linux errno extension */ +#define EBADE_STR "Invalid exchange" +#define EBADR 51 /* Linux errno extension */ +#define EBADR_STR "Invalid request descriptor" +#define EXFULL 52 /* Linux errno extension */ +#define EXFULL_STR "Exchange full" +#define ENOANO 53 /* Linux errno extension */ +#define ENOANO_STR "No anode" +#define EBADRQC 54 /* Linux errno extension */ +#define EBADRQC_STR "Invalid request code" +#define EBADSLT 55 /* Linux errno extension */ +#define EBADSLT_STR "Invalid slot" +#define EDEADLOCK 56 /* Linux errno extension */ +#define EDEADLOCK_STR "File locking deadlock error" +#define EBFONT 57 /* Linux errno extension */ +#define EBFONT_STR "Bad font file format" + +#define ENOSTR 60 +#define ENOSTR_STR "Device not a stream" +#define ENODATA 61 +#define ENODATA_STR "No data available" +#define ETIME 62 +#define ETIME_STR "Timer expired" +#define ENOSR 63 +#define ENOSR_STR "Out of streams resources" +#define ENONET 64 /* Linux errno extension */ +#define ENONET_STR "Machine is not on the network" +#define ENOPKG 65 /* Linux errno extension */ +#define ENOPKG_STR "Package not installed" +#define EREMOTE 66 /* Linux errno extension */ +#define EREMOTE_STR "Object is remote" +#define ENOLINK 67 +#define ENOLINK_STR "Link has been severed" +#define EADV 68 /* Linux errno extension */ +#define EADV_STR "Advertise error" +#define ESRMNT 69 /* Linux errno extension */ +#define ESRMNT_STR "Srmount error" +#define ECOMM 70 /* Linux errno extension */ +#define ECOMM_STR "Communication error on send" +#define EPROTO 71 +#define EPROTO_STR "Protocol error" + +#define EMULTIHOP 74 +#define EMULTIHOP_STR "Multihop attempted" +#define ELBIN 75 /* Linux errno extension */ +#define ELBIN_STR "Inode is remote" +#define EDOTDOT 76 /* Linux errno extension */ +#define EDOTDOT_STR "RFS specific error" +#define EBADMSG 77 +#define EBADMSG_STR "Not a data message" + +#define EFTYPE 79 +#define EFTYPE_STR "Inappropriate file type or format" +#define ENOTUNIQ 80 /* Linux errno extension */ +#define ENOTUNIQ_STR "Name not unique on network" +#define EBADFD 81 /* Linux errno extension */ +#define EBADFD_STR "File descriptor in bad state" +#define EREMCHG 82 /* Linux errno extension */ +#define EREMCHG_STR "Remote address changed" +#define ELIBACC 83 /* Linux errno extension */ +#define ELIBACC_STR "Can not access a needed shared library" +#define ELIBBAD 84 /* Linux errno extension */ +#define ELIBBAD_STR "Accessing a corrupted shared library" +#define ELIBSCN 85 /* Linux errno extension */ +#define ELIBSCN_STR ".lib section in a.out corrupted" +#define ELIBMAX 86 /* Linux errno extension */ +#define ELIBMAX_STR "Attempting to link in too many shared libraries" +#define ELIBEXEC 87 /* Linux errno extension */ +#define ELIBEXEC_STR "Cannot exec a shared library directly" +#define ENOSYS 88 +#define ENOSYS_STR "Function not implemented" +#define ENMFILE 89 /* Cygwin */ +#define ENMFILE_STR "No more files" +#define ENOTEMPTY 90 +#define ENOTEMPTY_STR "Directory not empty" +#define ENAMETOOLONG 91 +#define ENAMETOOLONG_STR "File name too long" +#define ELOOP 92 +#define ELOOP_STR "Too many symbolic links encountered" + +#define EOPNOTSUPP 95 +#define EOPNOTSUPP_STR "Operation not supported on transport endpoint" +#define EPFNOSUPPORT 96 +#define EPFNOSUPPORT_STR "Protocol family not supported" + +#define ECONNRESET 104 +#define ECONNRESET_STR "Connection reset by peer" +#define ENOBUFS 105 +#define ENOBUFS_STR "No buffer space available" +#define EAFNOSUPPORT 106 +#define EAFNOSUPPORT_STR "Address family not supported by protocol" +#define EPROTOTYPE 107 +#define EPROTOTYPE_STR "Protocol wrong type for socket" +#define ENOTSOCK 108 +#define ENOTSOCK_STR "Socket operation on non-socket" +#define ENOPROTOOPT 109 +#define ENOPROTOOPT_STR "Protocol not available" +#define ESHUTDOWN 110 /* Linux errno extension */ +#define ESHUTDOWN_STR "Cannot send after transport endpoint shutdown" +#define ECONNREFUSED 111 +#define ECONNREFUSED_STR "Connection refused" +#define EADDRINUSE 112 +#define EADDRINUSE_STR "Address already in use" +#define ECONNABORTED 113 +#define ECONNABORTED_STR "Software caused connection abort" +#define ENETUNREACH 114 +#define ENETUNREACH_STR "Network is unreachable" +#define ENETDOWN 115 +#define ENETDOWN_STR "Network is down" +#define ETIMEDOUT 116 +#define ETIMEDOUT_STR "Connection timed out" +#define EHOSTDOWN 117 +#define EHOSTDOWN_STR "Host is down" +#define EHOSTUNREACH 118 +#define EHOSTUNREACH_STR "No route to host" +#define EINPROGRESS 119 +#define EINPROGRESS_STR "Operation now in progress" +#define EALREADY 120 +#define EALREADY_STR "Socket already connected" +#define EDESTADDRREQ 121 +#define EDESTADDRREQ_STR "Destination address required" +#define EMSGSIZE 122 +#define EMSGSIZE_STR "Message too long" +#define EPROTONOSUPPORT 123 +#define EPROTONOSUPPORT_STR "Protocol not supported" +#define ESOCKTNOSUPPORT 124 /* Linux errno extension */ +#define ESOCKTNOSUPPORT_STR "Socket type not supported" +#define EADDRNOTAVAIL 125 +#define EADDRNOTAVAIL_STR "Cannot assign requested address" +#define ENETRESET 126 +#define ENETRESET_STR "Network dropped connection because of reset" +#define EISCONN 127 +#define EISCONN_STR "Transport endpoint is already connected" +#define ENOTCONN 128 +#define ENOTCONN_STR "Transport endpoint is not connected" +#define ETOOMANYREFS 129 +#define ETOOMANYREFS_STR "Too many references: cannot splice" +#define EPROCLIM 130 +#define EPROCLIM_STR "Limit would be exceeded by attempted fork" +#define EUSERS 131 +#define EUSERS_STR "Too many users" +#define EDQUOT 132 +#define EDQUOT_STR "Quota exceeded" +#define ESTALE 133 +#define ESTALE_STR "Stale NFS file handle" +#define ENOTSUP 134 +#define ENOTSUP_STR "Not supported" +#define ENOMEDIUM 135 /* Linux errno extension */ +#define ENOMEDIUM_STR "No medium found" +#define ENOSHARE 136 /* Cygwin */ +#define ENOSHARE_STR "No such host or network path" +#define ECASECLASH 137 /* Cygwin */ +#define ECASECLASH_STR "Filename exists with different case" +#define EILSEQ 138 +#define EILSEQ_STR "Illegal byte sequence" +#define EOVERFLOW 139 +#define EOVERFLOW_STR "Value too large for defined data type" +#define ECANCELED 140 +#define ECANCELED_STR "Operation cancelled" +#define ENOTRECOVERABLE 141 +#define ENOTRECOVERABLE_STR "State not recoverable" +#define EOWNERDEAD 142 +#define EOWNERDEAD_STR "Previous owner died" +#define ESTRPIPE 143 /* Linux errno extension */ +#define ESTRPIPE_STR "Streams pipe error" + +#define __ELASTERROR 2000 /* Users can add values starting here */ + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* Return a pointer to the thread specific errno. */ + +int *__errno(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_ERRNO_H */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_hc.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_hc.h new file mode 100644 index 00000000..7a12a98b --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_hc.h @@ -0,0 +1,213 @@ +/** + * @file usb_hc.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USB_HC_H +#define _USB_HC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*usbh_asynch_callback_t)(void *arg, int nbytes); +typedef void *usbh_epinfo_t; +/** + * @brief USB Endpoint Configuration. + * + * Structure containing the USB endpoint configuration. + */ +struct usbh_endpoint_cfg { + struct usbh_hubport *hport; + /** The number associated with the EP in the device + * configuration structure + * IN EP = 0x80 | \ + * OUT EP = 0x00 | \ + */ + uint8_t ep_addr; + /** Endpoint Transfer Type. + * May be Bulk, Interrupt, Control or Isochronous + */ + uint8_t ep_type; + uint8_t ep_interval; + /** Endpoint max packet size */ + uint16_t ep_mps; +}; + +/** + * @brief USB Host Core Layer API + * @defgroup _usb_host_core_api USB Host Core API + * @{ + */ + +/** + * @brief usb host controller hardware init. + * + * @return int + */ +int usb_hc_init(void); + +/** + * @brief reset roothub port + * + * @param port port index + * @return int + */ +int usbh_reset_port(const uint8_t port); + +/** + * @brief get roothub port speed + * + * @param port port index + * @return return 1 means USB_SPEED_LOW, 2 means USB_SPEED_FULL and 3 means USB_SPEED_HIGH. + */ +uint8_t usbh_get_port_speed(const uint8_t port); + +/** + * @brief reconfig control endpoint. + * + * @param ep A memory location provided by the caller. + * @param dev_addr device address. + * @param ep_mps control endpoint max packet size. + * @param speed port speed + * @return On success will return 0, and others indicate fail. + */ +int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uint8_t speed); + +/** + * @brief Allocate and config endpoint + * + * @param ep A memory location provided by the caller in which to save the allocated endpoint info. + * @param ep_cfg Describes the endpoint info to be allocated. + * @return On success will return 0, and others indicate fail. + */ +int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg); + +/** + * @brief Free a memory in which saves endpoint info. + * + * @param ep A memory location provided by the caller in which to free the allocated endpoint info. + * @return On success will return 0, and others indicate fail. + */ +int usbh_ep_free(usbh_epinfo_t ep); + +/** + * @brief Perform a control transfer. + * This is a blocking method; this method will not return until the transfer has completed. + * + * @param ep The control endpoint to send/receive the control request. + * @param setup Setup packet to be sent. + * @param buffer buffer used for sending the request and for returning any responses. This buffer must be large enough to hold the length value + * in the request description. + * @return On success will return 0, and others indicate fail. + */ +int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint8_t *buffer); + +/** + * @brief Process a request to handle a transfer descriptor. This method will + * enqueue the transfer request and wait for it to complete. Only one transfer may be queued; + * This is a blocking method; this method will not return until the transfer has completed. + * + * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer. + * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). + * @param buflen The length of the data to be sent or received. + * @return On success, a non-negative value is returned that indicates the number + * of bytes successfully transferred. On a failure, a negated errno value + * is returned that indicates the nature of the failure: + * + * EAGAIN - If devices NAKs the transfer (or NYET or other error where + * it may be appropriate to restart the entire transaction). + * EPERM - If the endpoint stalls + * EIO - On a TX or data toggle error + * EPIPE - Overrun errors + * + */ +int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen); + +/** + * @brief Process a request to handle a transfer descriptor. This method will + * enqueue the transfer request and wait for it to complete. Only one transfer may be queued; + * This is a blocking method; this method will not return until the transfer has completed. + * + * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer. + * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). + * @param buflen The length of the data to be sent or received. + * @return On success, a non-negative value is returned that indicates the number + * of bytes successfully transferred. On a failure, a negated errno value + * is returned that indicates the nature of the failure: + * + * EAGAIN - If devices NAKs the transfer (or NYET or other error where + * it may be appropriate to restart the entire transaction). + * EPERM - If the endpoint stalls + * EIO - On a TX or data toggle error + * EPIPE - Overrun errors + * + */ +int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen); + +/** + * @brief Process a request to handle a transfer asynchronously. This method + * will enqueue the transfer request and return immediately. Only one transfer may be queued on a given endpoint + * When the transfer completes, the callback will be invoked with the provided argument. + * + * This method is useful for receiving interrupt transfers which may come infrequently. + * + * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer. + * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). + * @param buflen The length of the data to be sent or received. + * @param callback This function will be called when the transfer completes. + * @param arg The arbitrary parameter that will be passed to the callback function when the transfer completes. + * + * @return On success will return 0, and others indicate fail. + */ +int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg); + +/** + * @brief Process a request to handle a transfer asynchronously. This method + * will enqueue the transfer request and return immediately. Only one transfer may be queued on a given endpoint + * When the transfer completes, the callback will be invoked with the provided argument. + * + * This method is useful for receiving interrupt transfers which may come infrequently. + * + * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer. + * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). + * @param buflen The length of the data to be sent or received. + * @param callback This function will be called when the transfer completes. + * @param arg The arbitrary parameter that will be passed to the callback function when the transfer completes. + * + * @return On success will return 0, and others indicate fail. + */ +int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, usbh_asynch_callback_t callback, void *arg); + +/** + * @brief Cancel any pending syncrhonous or asynchronous transfer on an endpoint. + * + * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to cancel. + * @return On success will return 0, and others indicate fail. + */ +int usb_ep_cancel(usbh_epinfo_t ep); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_list.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_list.h new file mode 100644 index 00000000..55111fda --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_list.h @@ -0,0 +1,473 @@ +/** + * @file usb_list.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef __USB_LIST_H__ +#define __USB_LIST_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * usb_container_of - return the member address of ptr, if the type of ptr is the + * struct type. + */ +#define usb_container_of(ptr, type, member) \ + ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member))) + +/** + * Single List structure + */ +struct usb_slist_node { + struct usb_slist_node *next; /**< point to next node. */ +}; +typedef struct usb_slist_node usb_slist_t; /**< Type for single list. */ + +/** + * @brief initialize a single list + * + * @param l the single list to be initialized + */ +static inline void usb_slist_init(usb_slist_t *l) +{ + l->next = NULL; +} + +static inline void usb_slist_add_head(usb_slist_t *l, usb_slist_t *n) +{ + n->next = l->next; + l->next = n; +} + +static inline void usb_slist_add_tail(usb_slist_t *l, usb_slist_t *n) +{ + while (l->next) { + l = l->next; + } + + /* append the node to the tail */ + l->next = n; + n->next = NULL; +} + +static inline void usb_slist_insert(usb_slist_t *l, usb_slist_t *next, usb_slist_t *n) +{ + if (!next) { + usb_slist_add_tail(next, l); + return; + } + + while (l->next) { + if (l->next == next) { + l->next = n; + n->next = next; + } + + l = l->next; + } +} + +static inline usb_slist_t *usb_slist_remove(usb_slist_t *l, usb_slist_t *n) +{ + /* remove slist head */ + while (l->next && l->next != n) { + l = l->next; + } + + /* remove node */ + if (l->next != (usb_slist_t *)0) { + l->next = l->next->next; + } + + return l; +} + +static inline unsigned int usb_slist_len(const usb_slist_t *l) +{ + unsigned int len = 0; + const usb_slist_t *list = l->next; + + while (list != NULL) { + list = list->next; + len++; + } + + return len; +} + +static inline unsigned int usb_slist_contains(usb_slist_t *l, usb_slist_t *n) +{ + while (l->next) { + if (l->next == n) { + return 0; + } + + l = l->next; + } + + return 1; +} + +static inline usb_slist_t *usb_slist_head(usb_slist_t *l) +{ + return l->next; +} + +static inline usb_slist_t *usb_slist_tail(usb_slist_t *l) +{ + while (l->next) { + l = l->next; + } + + return l; +} + +static inline usb_slist_t *usb_slist_next(usb_slist_t *n) +{ + return n->next; +} + +static inline int usb_slist_isempty(usb_slist_t *l) +{ + return l->next == NULL; +} + +/** + * @brief initialize a slist object + */ +#define USB_SLIST_OBJECT_INIT(object) \ + { \ + NULL \ + } + +/** + * @brief initialize a slist object + */ +#define USB_SLIST_DEFINE(slist) \ + usb_slist_t slist = { NULL } + +/** + * @brief get the struct for this single list node + * @param node the entry point + * @param type the type of structure + * @param member the name of list in structure + */ +#define usb_slist_entry(node, type, member) \ + usb_container_of(node, type, member) + +/** + * usb_slist_first_entry - get the first element from a slist + * @ptr: the slist head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the slist_struct within the struct. + * + * Note, that slist is expected to be not empty. + */ +#define usb_slist_first_entry(ptr, type, member) \ + usb_slist_entry((ptr)->next, type, member) + +/** + * usb_slist_tail_entry - get the tail element from a slist + * @ptr: the slist head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the slist_struct within the struct. + * + * Note, that slist is expected to be not empty. + */ +#define usb_slist_tail_entry(ptr, type, member) \ + usb_slist_entry(usb_slist_tail(ptr), type, member) + +/** + * usb_slist_first_entry_or_null - get the first element from a slist + * @ptr: the slist head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the slist_struct within the struct. + * + * Note, that slist is expected to be not empty. + */ +#define usb_slist_first_entry_or_null(ptr, type, member) \ + (usb_slist_isempty(ptr) ? NULL : usb_slist_first_entry(ptr, type, member)) + +/** + * usb_slist_for_each - iterate over a single list + * @pos: the usb_slist_t * to use as a loop cursor. + * @head: the head for your single list. + */ +#define usb_slist_for_each(pos, head) \ + for (pos = (head)->next; pos != NULL; pos = pos->next) + +#define usb_slist_for_each_safe(pos, next, head) \ + for (pos = (head)->next, next = pos->next; pos; \ + pos = next, next = pos->next) + +/** + * usb_slist_for_each_entry - iterate over single list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your single list. + * @member: the name of the list_struct within the struct. + */ +#define usb_slist_for_each_entry(pos, head, member) \ + for (pos = usb_slist_entry((head)->next, typeof(*pos), member); \ + &pos->member != (NULL); \ + pos = usb_slist_entry(pos->member.next, typeof(*pos), member)) + +#define usb_slist_for_each_entry_safe(pos, n, head, member) \ + for (pos = usb_slist_entry((head)->next, typeof(*pos), member), \ + n = usb_slist_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (NULL); \ + pos = n, n = usb_slist_entry(pos->member.next, typeof(*pos), member)) + +/** + * Double List structure + */ +struct usb_dlist_node { + struct usb_dlist_node *next; /**< point to next node. */ + struct usb_dlist_node *prev; /**< point to prev node. */ +}; +typedef struct usb_dlist_node usb_dlist_t; /**< Type for lists. */ + +/** + * @brief initialize a list + * + * @param l list to be initialized + */ +static inline void usb_dlist_init(usb_dlist_t *l) +{ + l->next = l->prev = l; +} + +/** + * @brief insert a node after a list + * + * @param l list to insert it + * @param n new node to be inserted + */ +static inline void usb_dlist_insert_after(usb_dlist_t *l, usb_dlist_t *n) +{ + l->next->prev = n; + n->next = l->next; + + l->next = n; + n->prev = l; +} + +/** + * @brief insert a node before a list + * + * @param n new node to be inserted + * @param l list to insert it + */ +static inline void usb_dlist_insert_before(usb_dlist_t *l, usb_dlist_t *n) +{ + l->prev->next = n; + n->prev = l->prev; + + l->prev = n; + n->next = l; +} + +/** + * @brief remove node from list. + * @param n the node to remove from the list. + */ +static inline void usb_dlist_remove(usb_dlist_t *n) +{ + n->next->prev = n->prev; + n->prev->next = n->next; + + n->next = n->prev = n; +} + +/** + * @brief move node from list. + * @param n the node to remove from the list. + */ +static inline void usb_dlist_move_head(usb_dlist_t *l, usb_dlist_t *n) +{ + usb_dlist_remove(n); + usb_dlist_insert_after(l, n); +} + +/** + * @brief move node from list. + * @param n the node to remove from the list. + */ +static inline void usb_dlist_move_tail(usb_dlist_t *l, usb_dlist_t *n) +{ + usb_dlist_remove(n); + usb_dlist_insert_before(l, n); +} + +/** + * @brief tests whether a list is empty + * @param l the list to test. + */ +static inline int usb_dlist_isempty(const usb_dlist_t *l) +{ + return l->next == l; +} + +/** + * @brief get the list length + * @param l the list to get. + */ +static inline unsigned int usb_dlist_len(const usb_dlist_t *l) +{ + unsigned int len = 0; + const usb_dlist_t *p = l; + + while (p->next != l) { + p = p->next; + len++; + } + + return len; +} + +/** + * @brief initialize a dlist object + */ +#define USB_DLIST_OBJECT_INIT(object) \ + { \ + &(object), &(object) \ + } +/** + * @brief initialize a dlist object + */ +#define USB_DLIST_DEFINE(list) \ + usb_dlist_t list = { &(list), &(list) } + +/** + * @brief get the struct for this entry + * @param node the entry point + * @param type the type of structure + * @param member the name of list in structure + */ +#define usb_dlist_entry(node, type, member) \ + usb_container_of(node, type, member) + +/** + * dlist_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define usb_dlist_first_entry(ptr, type, member) \ + usb_dlist_entry((ptr)->next, type, member) +/** + * dlist_first_entry_or_null - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define usb_dlist_first_entry_or_null(ptr, type, member) \ + (usb_dlist_isempty(ptr) ? NULL : usb_dlist_first_entry(ptr, type, member)) + +/** + * usb_dlist_for_each - iterate over a list + * @pos: the usb_dlist_t * to use as a loop cursor. + * @head: the head for your list. + */ +#define usb_dlist_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * usb_dlist_for_each_prev - iterate over a list + * @pos: the dlist_t * to use as a loop cursor. + * @head: the head for your list. + */ +#define usb_dlist_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/** + * usb_dlist_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the dlist_t * to use as a loop cursor. + * @n: another dlist_t * to use as temporary storage + * @head: the head for your list. + */ +#define usb_dlist_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +#define usb_dlist_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; pos != (head); \ + pos = n, n = pos->prev) +/** + * usb_dlist_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define usb_dlist_for_each_entry(pos, head, member) \ + for (pos = usb_dlist_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = usb_dlist_entry(pos->member.next, typeof(*pos), member)) + +/** + * usb_usb_dlist_for_each_entry_reverse - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define usb_dlist_for_each_entry_reverse(pos, head, member) \ + for (pos = usb_dlist_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = usb_dlist_entry(pos->member.prev, typeof(*pos), member)) + +/** + * usb_usb_dlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define usb_dlist_for_each_entry_safe(pos, n, head, member) \ + for (pos = usb_dlist_entry((head)->next, typeof(*pos), member), \ + n = usb_dlist_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = usb_dlist_entry(n->member.next, typeof(*n), member)) + +/** + * usb_usb_dlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define usb_dlist_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = usb_dlist_entry((head)->prev, typeof(*pos), field), \ + n = usb_dlist_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = usb_dlist_entry(pos->member.prev, typeof(*pos), member)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_mem.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_mem.h new file mode 100644 index 00000000..7f518b0c --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_mem.h @@ -0,0 +1,75 @@ +/** + * @file usb_mem.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USB_MEM_H +#define _USB_MEM_H + +#define DCACHE_LINE_SIZE 32 +#define DCACHE_LINEMASK (DCACHE_LINE_SIZE - 1) + +#ifdef CONFIG_USB_DCACHE_ENABLE +#ifdef CONFIG_USB_NOCACHE_RAM +#define USB_MEM_ALIGN32 +#define USB_NOCACHE_RAM_SECTION __attribute__((section(".nocache_ram"))) +#else +#define USB_MEM_ALIGN32 __attribute__((aligned(DCACHE_LINE_SIZE))) +#define USB_NOCACHE_RAM_SECTION +#endif +#else +#define USB_MEM_ALIGN32 +#define USB_NOCACHE_RAM_SECTION +#endif + +static inline void *usb_malloc(size_t size) +{ + return malloc(size); +} + +static inline void usb_free(void *ptr) +{ + free(ptr); +} + +#ifdef CONFIG_USB_DCACHE_ENABLE +static inline void *usb_iomalloc(size_t size) +{ + size = (size + DCACHE_LINEMASK) & ~DCACHE_LINEMASK; + return malloc(size); +} + +static inline void usb_iofree(void *addr) +{ + free(addr); +} +#else +static inline void *usb_iomalloc(size_t size) +{ + return malloc(size); +} + +static inline void usb_iofree(void *ptr) +{ + free(ptr); +} +#endif + +#endif \ No newline at end of file diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_util.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_util.h new file mode 100644 index 00000000..d21a5f61 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/common/usb_util.h @@ -0,0 +1,300 @@ +/** + * @file usb_util.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USB_UTIL_H +#define _USB_UTIL_H + +#include +#include +#include +#include +#include +#include "usb_errno.h" +#include "usb_list.h" +#include "usb_mem.h" + +#if defined(__CC_ARM) +#ifndef __USED +#define __USED __attribute__((used)) +#endif +#ifndef __WEAK +#define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED +#define __PACKED __attribute__((packed)) +#endif +#ifndef __PACKED_STRUCT +#define __PACKED_STRUCT __packed struct +#endif +#ifndef __PACKED_UNION +#define __PACKED_UNION __packed union +#endif +#ifndef __ALIGNED +#define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#elif defined(__GNUC__) +#ifndef __USED +#define __USED __attribute__((used)) +#endif +#ifndef __WEAK +#define __WEAK __attribute__((weak)) +#endif +#ifndef __PACKED +#define __PACKED __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_STRUCT +#define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#endif +#ifndef __PACKED_UNION +#define __PACKED_UNION union __attribute__((packed, aligned(1))) +#endif +#ifndef __ALIGNED +#define __ALIGNED(x) __attribute__((aligned(x))) +#endif +#elif defined(__ICCARM__) +#ifndef __USED +#if __ICCARM_V8 +#define __USED __attribute__((used)) +#else +#define __USED _Pragma("__root") +#endif +#endif + +#ifndef __WEAK +#if __ICCARM_V8 +#define __WEAK __attribute__((weak)) +#else +#define __WEAK _Pragma("__weak") +#endif +#endif + +#ifndef __PACKED +#if __ICCARM_V8 +#define __PACKED __attribute__((packed, aligned(1))) +#else +/* Needs IAR language extensions */ +#define __PACKED __packed +#endif +#endif + +#ifndef __PACKED_STRUCT +#if __ICCARM_V8 +#define __PACKED_STRUCT struct __attribute__((packed, aligned(1))) +#else +/* Needs IAR language extensions */ +#define __PACKED_STRUCT __packed struct +#endif +#endif + +#ifndef __PACKED_UNION +#if __ICCARM_V8 +#define __PACKED_UNION union __attribute__((packed, aligned(1))) +#else +/* Needs IAR language extensions */ +#define __PACKED_UNION __packed union +#endif +#endif + +#ifndef __ALIGNED +#if __ICCARM_V8 +#define __ALIGNED(x) __attribute__((aligned(x))) +#elif (__VER__ >= 7080000) +/* Needs IAR language extensions */ +#define __ALIGNED(x) __attribute__((aligned(x))) +#else +#warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored. +#define __ALIGNED(x) +#endif +#endif + +#endif + +#ifndef __ALIGN_BEGIN +#define __ALIGN_BEGIN +#endif +#ifndef __ALIGN_END +#define __ALIGN_END __attribute__((aligned(4))) +#endif + +#ifndef ARG_UNUSED +#define ARG_UNUSED(x) (void)(x) +#endif + +#ifndef LO_BYTE +#define LO_BYTE(x) ((uint8_t)(x & 0x00FF)) +#endif + +#ifndef HI_BYTE +#define HI_BYTE(x) ((uint8_t)((x & 0xFF00) >> 8)) +#endif + +/** + * @def MAX + * @brief The larger value between @p a and @p b. + * @note Arguments are evaluated twice. + */ +#ifndef MAX +/* Use Z_MAX for a GCC-only, single evaluation version */ +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + +/** + * @def MIN + * @brief The smaller value between @p a and @p b. + * @note Arguments are evaluated twice. + */ +#ifndef MIN +/* Use Z_MIN for a GCC-only, single evaluation version */ +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef BCD +#define BCD(x) ((((x) / 10) << 4) | ((x) % 10)) +#endif + +#ifdef BIT +#undef BIT +#define BIT(n) (1UL << (n)) +#else +#define BIT(n) (1UL << (n)) +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) \ + ((int)((sizeof(array) / sizeof((array)[0])))) +#endif + +#ifndef BSWAP16 +#define BSWAP16(u16) (__builtin_bswap16(u16)) +#endif +#ifndef BSWAP32 +#define BSWAP32(u32) (__builtin_bswap32(u32)) +#endif + +#define GET_BE16(field) \ + (((uint16_t)(field)[0] << 8) | ((uint16_t)(field)[1])) + +#define GET_BE32(field) \ + (((uint32_t)(field)[0] << 24) | ((uint32_t)(field)[1] << 16) | ((uint32_t)(field)[2] << 8) | ((uint32_t)(field)[3] << 0)) + +#define SET_BE16(field, value) \ + do { \ + (field)[0] = (uint8_t)((value) >> 8); \ + (field)[1] = (uint8_t)((value) >> 0); \ + } while (0) + +#define SET_BE24(field, value) \ + do { \ + (field)[0] = (uint8_t)((value) >> 16); \ + (field)[1] = (uint8_t)((value) >> 8); \ + (field)[2] = (uint8_t)((value) >> 0); \ + } while (0) + +#define SET_BE32(field, value) \ + do { \ + (field)[0] = (uint8_t)((value) >> 24); \ + (field)[1] = (uint8_t)((value) >> 16); \ + (field)[2] = (uint8_t)((value) >> 8); \ + (field)[3] = (uint8_t)((value) >> 0); \ + } while (0) + +#define REQTYPE_GET_DIR(x) (((x) >> 7) & 0x01) +#define REQTYPE_GET_TYPE(x) (((x) >> 5) & 0x03U) +#define REQTYPE_GET_RECIP(x) ((x)&0x1F) + +#define GET_DESC_TYPE(x) (((x) >> 8) & 0xFFU) +#define GET_DESC_INDEX(x) ((x)&0xFFU) + +#define WBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF) +#define DBVAL(x) (x & 0xFF), ((x >> 8) & 0xFF), ((x >> 16) & 0xFF), ((x >> 24) & 0xFF) + +#define USB_DESC_SECTION __attribute__((section("usb_desc"))) __USED __ALIGNED(1) + +/* DEBUG level */ +#define USB_DBG_ERROR 0 +#define USB_DBG_WARNING 1 +#define USB_DBG_INFO 2 +#define USB_DBG_LOG 3 + +#ifndef USB_DBG_LEVEL +#define USB_DBG_LEVEL USB_DBG_INFO +#endif + +#ifndef USB_DBG_TAG +#define USB_DBG_TAG "USB" +#endif +/* + * The color for terminal (foreground) + * BLACK 30 + * RED 31 + * GREEN 32 + * YELLOW 33 + * BLUE 34 + * PURPLE 35 + * CYAN 36 + * WHITE 37 + */ +#define _USB_DBG_COLOR(n) printf("\033[" #n "m") +#define _USB_DBG_LOG_HDR(lvl_name, color_n) \ + printf("\033[" #color_n "m[" lvl_name "/" USB_DBG_TAG "] ") +#define _USB_DBG_LOG_X_END \ + printf("\033[0m") + +#define usb_dbg_log_line(lvl, color_n, fmt, ...) \ + do { \ + _USB_DBG_LOG_HDR(lvl, color_n); \ + printf(fmt, ##__VA_ARGS__); \ + _USB_DBG_LOG_X_END; \ + } while (0) + +#if (USB_DBG_LEVEL >= USB_DBG_LOG) +#define USB_LOG_DBG(fmt, ...) usb_dbg_log_line("D", 0, fmt, ##__VA_ARGS__) +#else +#define USB_LOG_DBG(...) +#endif + +#if (USB_DBG_LEVEL >= USB_DBG_INFO) +#define USB_LOG_INFO(fmt, ...) usb_dbg_log_line("I", 32, fmt, ##__VA_ARGS__) +#else +#define USB_LOG_INFO(...) +#endif + +#if (USB_DBG_LEVEL >= USB_DBG_WARNING) +#define USB_LOG_WRN(fmt, ...) usb_dbg_log_line("W", 33, fmt, ##__VA_ARGS__) +#else +#define USB_LOG_WRN(...) +#endif + +#if (USB_DBG_LEVEL >= USB_DBG_ERROR) +#define USB_LOG_ERR(fmt, ...) usb_dbg_log_line("E", 31, fmt, ##__VA_ARGS__) +#else +#define USB_LOG_ERR(...) +#endif + +void usb_assert(const char *filename, int linenum); +#define USB_ASSERT(f) \ + do { \ + if (!(f)) \ + usb_assert(__FILE__, __LINE__); \ + } while (0) + +#endif diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbd_core.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbd_core.c new file mode 100644 index 00000000..ce4e4abc --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbd_core.c @@ -0,0 +1,1299 @@ +/** + * @file usbd_core.c + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbd_core.h" + +#define USBD_EP_CALLBACK_LIST_SEARCH 0 +#define USBD_EP_CALLBACK_ARR_SEARCH 1 +#define USBD_EP_CALLBACK_SEARCH_METHOD USBD_EP_CALLBACK_ARR_SEARCH + +/* general descriptor field offsets */ +#define DESC_bLength 0 /** Length offset */ +#define DESC_bDescriptorType 1 /** Descriptor type offset */ + +/* config descriptor field offsets */ +#define CONF_DESC_wTotalLength 2 /** Total length offset */ +#define CONF_DESC_bConfigurationValue 5 /** Configuration value offset */ +#define CONF_DESC_bmAttributes 7 /** configuration characteristics */ + +/* interface descriptor field offsets */ +#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */ +#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */ + +#define USB_REQUEST_BUFFER_SIZE 256 +#define USB_EP_OUT_NUM 8 +#define USB_EP_IN_NUM 8 + +static struct usbd_core_cfg_priv { + /** Setup packet */ + struct usb_setup_packet setup; + /** Pointer to data buffer */ + uint8_t *ep0_data_buf; + /** Remaining bytes in buffer */ + uint32_t ep0_data_buf_residue; + /** Total length of control transfer */ + uint32_t ep0_data_buf_len; + /** Zero length packet flag of control transfer */ + bool zlp_flag; + /** Pointer to registered descriptors */ + const uint8_t *descriptors; + /* Buffer used for storing standard, class and vendor request data */ + uint8_t req_data[USB_REQUEST_BUFFER_SIZE]; + +#if USBD_EP_CALLBACK_SEARCH_METHOD == USBD_EP_CALLBACK_ARR_SEARCH + usbd_endpoint_callback in_ep_cb[USB_EP_IN_NUM]; + usbd_endpoint_callback out_ep_cb[USB_EP_OUT_NUM]; +#endif + /** Variable to check whether the usb has been configured */ + bool configured; + /** Currently selected configuration */ + uint8_t configuration; + /** Remote wakeup feature status */ + uint16_t remote_wakeup; + uint8_t reserved; +} usbd_core_cfg; + +static usb_slist_t usbd_class_head = USB_SLIST_OBJECT_INIT(usbd_class_head); +static struct usb_msosv1_descriptor *msosv1_desc; +static struct usb_msosv2_descriptor *msosv2_desc; +static struct usb_bos_descriptor *bos_desc; + +/** + * @brief print the contents of a setup packet + * + * @param [in] setup The setup packet + * + */ +static void usbd_print_setup(struct usb_setup_packet *setup) +{ + USB_LOG_INFO("Setup: " + "bmRequestType 0x%02x, bRequest 0x%02x, wValue 0x%04x, wIndex 0x%04x, wLength 0x%04x\r\n", + setup->bmRequestType, + setup->bRequest, + setup->wValue, + setup->wIndex, + setup->wLength); +} + +/** + * @brief Check if the device is in Configured state + * + * @return true if Configured, false otherwise. + */ +static bool is_device_configured(void) +{ + return (usbd_core_cfg.configuration != 0); +} +/** + * @brief Check if the interface of given number is valid + * + * @param [in] interface Number of the addressed interface + * + * This function searches through descriptor and checks + * is the Host has addressed valid interface. + * + * @return true if interface exists - valid + */ +static bool is_interface_valid(uint8_t interface) +{ + const uint8_t *p = (uint8_t *)usbd_core_cfg.descriptors; + const struct usb_configuration_descriptor *cfg_descr; + + /* Search through descriptor for matching interface */ + while (p[DESC_bLength] != 0U) { + if (p[DESC_bDescriptorType] == USB_DESCRIPTOR_TYPE_CONFIGURATION) { + cfg_descr = (const struct usb_configuration_descriptor *)p; + + if (interface < cfg_descr->bNumInterfaces) { + return true; + } + } + + p += p[DESC_bLength]; + } + + return false; +} +/** + * @brief Check if the endpoint of given address is valid + * + * @param [in] ep Address of the Endpoint + * + * This function checks if the Endpoint of given address + * is valid for the configured device. Valid Endpoint is + * either Control Endpoint or one used by the device. + * + * @return true if endpoint exists - valid + */ +static bool is_ep_valid(uint8_t ep) +{ + /* Check if its Endpoint 0 */ + if ((ep & 0x7f) == 0) { + return true; + } + + return true; +} +#if USBD_EP_CALLBACK_SEARCH_METHOD == USBD_EP_CALLBACK_ARR_SEARCH +static void usbd_ep_callback_register(void) +{ + usb_slist_t *i, *j, *k; + usb_slist_for_each(i, &usbd_class_head) + { + usbd_class_t *devclass = usb_slist_entry(i, struct usbd_class, list); + + usb_slist_for_each(j, &devclass->intf_list) + { + usbd_interface_t *intf = usb_slist_entry(j, struct usbd_interface, list); + + usb_slist_for_each(k, &intf->ep_list) + { + usbd_endpoint_t *ept = usb_slist_entry(k, struct usbd_endpoint, list); + + if (ept->ep_cb) { + if (ept->ep_addr & 0x80) { + usbd_core_cfg.in_ep_cb[ept->ep_addr & 0x7f] = ept->ep_cb; + } else { + usbd_core_cfg.out_ep_cb[ept->ep_addr & 0x7f] = ept->ep_cb; + } + } + } + } + } +} +#endif +/** + * @brief configure and enable endpoint + * + * This function sets endpoint configuration according to one specified in USB + * endpoint descriptor and then enables it for data transfers. + * + * @param [in] ep_desc Endpoint descriptor byte array + * + * @return true if successfully configured and enabled + */ +static bool usbd_set_endpoint(const struct usb_endpoint_descriptor *ep_desc) +{ + struct usbd_endpoint_cfg ep_cfg; + + ep_cfg.ep_addr = ep_desc->bEndpointAddress; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_type = ep_desc->bmAttributes & USBD_EP_TYPE_MASK; + + USB_LOG_INFO("Open endpoint:0x%x type:%u mps:%u\r\n", + ep_cfg.ep_addr, ep_cfg.ep_type, ep_cfg.ep_mps); + + usbd_ep_open(&ep_cfg); + usbd_core_cfg.configured = true; + + return true; +} +/** + * @brief Disable endpoint for transferring data + * + * This function cancels transfers that are associated with endpoint and + * disabled endpoint itself. + * + * @param [in] ep_desc Endpoint descriptor byte array + * + * @return true if successfully deconfigured and disabled + */ +static bool usbd_reset_endpoint(const struct usb_endpoint_descriptor *ep_desc) +{ + struct usbd_endpoint_cfg ep_cfg; + + ep_cfg.ep_addr = ep_desc->bEndpointAddress; + ep_cfg.ep_mps = ep_desc->wMaxPacketSize; + ep_cfg.ep_type = ep_desc->bmAttributes & USBD_EP_TYPE_MASK; + + USB_LOG_INFO("Close endpoint:0x%x type:%u\r\n", + ep_cfg.ep_addr, ep_cfg.ep_type); + + usbd_ep_close(ep_cfg.ep_addr); + + return true; +} + +/** + * @brief get specified USB descriptor + * + * This function parses the list of installed USB descriptors and attempts + * to find the specified USB descriptor. + * + * @param [in] type_index Type and index of the descriptor + * @param [out] data Descriptor data + * @param [out] len Descriptor length + * + * @return true if the descriptor was found, false otherwise + */ +static bool usbd_get_descriptor(uint16_t type_index, uint8_t **data, uint32_t *len) +{ + uint8_t type = 0U; + uint8_t index = 0U; + uint8_t *p = NULL; + uint32_t cur_index = 0U; + bool found = false; + + type = GET_DESC_TYPE(type_index); + index = GET_DESC_INDEX(type_index); + + if ((type == USB_DESCRIPTOR_TYPE_STRING) && (index == USB_OSDESC_STRING_DESC_INDEX)) { + USB_LOG_INFO("read MS OS 2.0 descriptor string\r\n"); + + if (!msosv1_desc) { + return false; + } + + *data = (uint8_t *)msosv1_desc->string; + *len = msosv1_desc->string_len; + + return true; + } else if (type == USB_DESCRIPTOR_TYPE_BINARY_OBJECT_STORE) { + USB_LOG_INFO("read BOS descriptor string\r\n"); + + if (!bos_desc) { + return false; + } + + *data = bos_desc->string; + *len = bos_desc->string_len; + return true; + } + /* + * Invalid types of descriptors, + * see USB Spec. Revision 2.0, 9.4.3 Get Descriptor + */ + else if ((type == USB_DESCRIPTOR_TYPE_INTERFACE) || (type == USB_DESCRIPTOR_TYPE_ENDPOINT) || +#ifndef CONFIG_USB_HS + (type > USB_DESCRIPTOR_TYPE_ENDPOINT)) { +#else + (type > USB_DESCRIPTOR_TYPE_OTHER_SPEED)) { +#endif + return false; + } + + p = (uint8_t *)usbd_core_cfg.descriptors; + + cur_index = 0U; + + while (p[DESC_bLength] != 0U) { + if (p[DESC_bDescriptorType] == type) { + if (cur_index == index) { + found = true; + break; + } + + cur_index++; + } + + /* skip to next descriptor */ + p += p[DESC_bLength]; + } + + if (found) { + /* set data pointer */ + *data = p; + + /* get length from structure */ + if (type == USB_DESCRIPTOR_TYPE_CONFIGURATION) { + /* configuration descriptor is an + * exception, length is at offset + * 2 and 3 + */ + *len = (p[CONF_DESC_wTotalLength]) | + (p[CONF_DESC_wTotalLength + 1] << 8); + } else { + /* normally length is at offset 0 */ + *len = p[DESC_bLength]; + } + } else { + /* nothing found */ + USB_LOG_ERR("descriptor not found!\r\n", type, index); + } + + return found; +} + +/** + * @brief set USB configuration + * + * This function configures the device according to the specified configuration + * index and alternate setting by parsing the installed USB descriptor list. + * A configuration index of 0 unconfigures the device. + * + * @param [in] config_index Configuration index + * @param [in] alt_setting Alternate setting number + * + * @return true if successfully configured false if error or unconfigured + */ +static bool usbd_set_configuration(uint8_t config_index, uint8_t alt_setting) +{ + uint8_t *p = (uint8_t *)usbd_core_cfg.descriptors; + uint8_t cur_alt_setting = 0xFF; + uint8_t cur_config = 0xFF; + bool found = false; + + if (config_index == 0U) { + /* TODO: unconfigure device */ + USB_LOG_ERR("Device not configured - invalid configuration\r\n"); + return true; + } + + /* configure endpoints for this configuration/altsetting */ + while (p[DESC_bLength] != 0U) { + switch (p[DESC_bDescriptorType]) { + case USB_DESCRIPTOR_TYPE_CONFIGURATION: + /* remember current configuration index */ + cur_config = p[CONF_DESC_bConfigurationValue]; + + if (cur_config == config_index) { + found = true; + } + + break; + + case USB_DESCRIPTOR_TYPE_INTERFACE: + /* remember current alternate setting */ + cur_alt_setting = + p[INTF_DESC_bAlternateSetting]; + break; + + case USB_DESCRIPTOR_TYPE_ENDPOINT: + if ((cur_config != config_index) || + (cur_alt_setting != alt_setting)) { + break; + } + + found = usbd_set_endpoint((struct usb_endpoint_descriptor *)p); + break; + + default: + break; + } + + /* skip to next descriptor */ + p += p[DESC_bLength]; + } + + return found; +} + +/** + * @brief set USB interface + * + * @param [in] iface Interface index + * @param [in] alt_setting Alternate setting number + * + * @return true if successfully configured false if error or unconfigured + */ +static bool usbd_set_interface(uint8_t iface, uint8_t alt_setting) +{ + const uint8_t *p = usbd_core_cfg.descriptors; + const uint8_t *if_desc = NULL; + struct usb_endpoint_descriptor *ep_desc; + uint8_t cur_alt_setting = 0xFF; + uint8_t cur_iface = 0xFF; + bool ret = false; + + USB_LOG_DBG("iface %u alt_setting %u\r\n", iface, alt_setting); + + while (p[DESC_bLength] != 0U) { + switch (p[DESC_bDescriptorType]) { + case USB_DESCRIPTOR_TYPE_INTERFACE: + /* remember current alternate setting */ + cur_alt_setting = p[INTF_DESC_bAlternateSetting]; + cur_iface = p[INTF_DESC_bInterfaceNumber]; + + if (cur_iface == iface && + cur_alt_setting == alt_setting) { + if_desc = (void *)p; + } + + USB_LOG_DBG("Current iface %u alt setting %u", + cur_iface, cur_alt_setting); + break; + + case USB_DESCRIPTOR_TYPE_ENDPOINT: + if (cur_iface == iface) { + ep_desc = (struct usb_endpoint_descriptor *)p; + + if (cur_alt_setting != alt_setting) { + ret = usbd_reset_endpoint(ep_desc); + } else { + ret = usbd_set_endpoint(ep_desc); + } + } + + break; + + default: + break; + } + + /* skip to next descriptor */ + p += p[DESC_bLength]; + } + + usbd_event_notify_handler(USBD_EVENT_SET_INTERFACE, (void *)if_desc); + + return ret; +} + +/** + * @brief handle a standard device request + * + * @param [in] setup The setup packet + * @param [in,out] data Data buffer + * @param [in,out] len Pointer to data length + * + * @return true if the request was handled successfully + */ +static bool usbd_std_device_req_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + uint16_t value = setup->wValue; + // uint16_t index = setup->wIndex; + bool ret = true; + + switch (setup->bRequest) { + case USB_REQUEST_GET_STATUS: + USB_LOG_DBG("REQ_GET_STATUS\r\n"); + /* bit 0: self-powered */ + /* bit 1: remote wakeup */ + *data = (uint8_t *)&usbd_core_cfg.remote_wakeup; + + *len = 2; + break; + + case USB_REQUEST_CLEAR_FEATURE: + USB_LOG_DBG("REQ_CLEAR_FEATURE\r\n"); + ret = false; + + if (value == USB_FEATURE_REMOTE_WAKEUP) { + usbd_core_cfg.remote_wakeup = 0; + usbd_event_notify_handler(USBD_EVENT_CLEAR_REMOTE_WAKEUP, NULL); + ret = true; + } + + break; + + case USB_REQUEST_SET_FEATURE: + USB_LOG_DBG("REQ_SET_FEATURE\r\n"); + ret = false; + + if (value == USB_FEATURE_REMOTE_WAKEUP) { + usbd_core_cfg.remote_wakeup = 1; + usbd_event_notify_handler(USBD_EVENT_SET_REMOTE_WAKEUP, NULL); + ret = true; + } + + if (value == USB_FEATURE_TEST_MODE) { + /* put TEST_MODE code here */ + } + + break; + + case USB_REQUEST_SET_ADDRESS: + USB_LOG_DBG("REQ_SET_ADDRESS, addr 0x%x\r\n", value); + usbd_set_address(value); + break; + + case USB_REQUEST_GET_DESCRIPTOR: + USB_LOG_DBG("REQ_GET_DESCRIPTOR\r\n"); + ret = usbd_get_descriptor(value, data, len); + break; + + case USB_REQUEST_SET_DESCRIPTOR: + USB_LOG_DBG("Device req 0x%02x not implemented\r\n", setup->bRequest); + ret = false; + break; + + case USB_REQUEST_GET_CONFIGURATION: + USB_LOG_DBG("REQ_GET_CONFIGURATION\r\n"); + /* indicate if we are configured */ + *data = (uint8_t *)&usbd_core_cfg.configuration; + *len = 1; + break; + + case USB_REQUEST_SET_CONFIGURATION: + value &= 0xFF; + USB_LOG_DBG("REQ_SET_CONFIGURATION, conf 0x%x\r\n", value); + + if (!usbd_set_configuration(value, 0)) { + USB_LOG_DBG("USB Set Configuration failed\r\n"); + ret = false; + } else { + /* configuration successful, + * update current configuration + */ + usbd_core_cfg.configuration = value; + usbd_event_notify_handler(USBD_EVENT_CONFIGURED, NULL); + } + + break; + + case USB_REQUEST_GET_INTERFACE: + break; + + case USB_REQUEST_SET_INTERFACE: + break; + + default: + USB_LOG_ERR("Illegal device req 0x%02x\r\n", setup->bRequest); + ret = false; + break; + } + + return ret; +} + +/** + * @brief handle a standard interface request + * + * @param [in] setup The setup packet + * @param [in,out] data Data buffer + * @param [in,out] len Pointer to data length + * + * @return true if the request was handled successfully + */ +static bool usbd_std_interface_req_handler(struct usb_setup_packet *setup, + uint8_t **data, uint32_t *len) +{ + /** The device must be configured to accept standard interface + * requests and the addressed Interface must be valid. + */ + if (!is_device_configured() || + (!is_interface_valid((uint8_t)setup->wIndex))) { + return false; + } + + switch (setup->bRequest) { + case USB_REQUEST_GET_STATUS: + /* no bits specified */ + *data = (uint8_t *)&usbd_core_cfg.remote_wakeup; + + *len = 2; + break; + + case USB_REQUEST_CLEAR_FEATURE: + case USB_REQUEST_SET_FEATURE: + /* not defined for interface */ + return false; + + case USB_REQUEST_GET_INTERFACE: + /** This handler is called for classes that does not support + * alternate Interfaces so always return 0. Classes that + * support alternative interfaces handles GET_INTERFACE + * in custom_handler. + */ + *data = (uint8_t *)&usbd_core_cfg.reserved; + + *len = 1; + break; + + case USB_REQUEST_SET_INTERFACE: + USB_LOG_DBG("REQ_SET_INTERFACE\r\n"); + usbd_set_interface(setup->wIndex, setup->wValue); + break; + + default: + USB_LOG_ERR("Illegal interface req 0x%02x\r\n", setup->bRequest); + return false; + } + + return true; +} + +/** + * @brief handle a standard endpoint request + * + * @param [in] setup The setup packet + * @param [in,out] data Data buffer + * @param [in,out] len Pointer to data length + * + * @return true if the request was handled successfully + */ +static bool usbd_std_endpoint_req_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + uint8_t ep = (uint8_t)setup->wIndex; + + /* Check if request addresses valid Endpoint */ + if (!is_ep_valid(ep)) { + return false; + } + + switch (setup->bRequest) { + case USB_REQUEST_GET_STATUS: + + /** This request is valid for Control Endpoints when + * the device is not yet configured. For other + * Endpoints the device must be configured. + * Firstly check if addressed ep is Control Endpoint. + * If no then the device must be in Configured state + * to accept the request. + */ + if (((ep & 0x7f) == 0) || is_device_configured()) { + /* bit 0 - Endpoint halted or not */ + usbd_ep_is_stalled(ep, (uint8_t *)&usbd_core_cfg.remote_wakeup); + *data = (uint8_t *)&usbd_core_cfg.remote_wakeup; + + *len = 2; + break; + } + + return false; + + case USB_REQUEST_CLEAR_FEATURE: + if (setup->wValue == USB_FEATURE_ENDPOINT_HALT) { + /** This request is valid for Control Endpoints when + * the device is not yet configured. For other + * Endpoints the device must be configured. + * Firstly check if addressed ep is Control Endpoint. + * If no then the device must be in Configured state + * to accept the request. + */ + if (((ep & 0x7f) == 0) || is_device_configured()) { + USB_LOG_ERR("ep:%x clear halt\r\n", ep); + usbd_ep_clear_stall(ep); + usbd_event_notify_handler(USBD_EVENT_CLEAR_HALT, NULL); + break; + } + } + + /* only ENDPOINT_HALT defined for endpoints */ + return false; + + case USB_REQUEST_SET_FEATURE: + if (setup->wValue == USB_FEATURE_ENDPOINT_HALT) { + /** This request is valid for Control Endpoints when + * the device is not yet configured. For other + * Endpoints the device must be configured. + * Firstly check if addressed ep is Control Endpoint. + * If no then the device must be in Configured state + * to accept the request. + */ + if (((ep & 0x7f) == 0) || is_device_configured()) { + /* set HALT by stalling */ + USB_LOG_ERR("ep:%x set halt\r\n", ep); + usbd_ep_set_stall(ep); + usbd_event_notify_handler(USBD_EVENT_SET_HALT, NULL); + break; + } + } + + /* only ENDPOINT_HALT defined for endpoints */ + return false; + + case USB_REQUEST_SYNCH_FRAME: + + /* For Synch Frame request the device must be configured */ + if (is_device_configured()) { + /* Not supported, return false anyway */ + USB_LOG_DBG("ep req 0x%02x not implemented\r\n", setup->bRequest); + } + + return false; + + default: + USB_LOG_ERR("Illegal ep req 0x%02x\r\n", setup->bRequest); + return false; + } + + return true; +} + +/** + * @brief default handler for standard ('chapter 9') requests + * + * If a custom request handler was installed, this handler is called first. + * + * @param [in] setup The setup packet + * @param [in,out] data Data buffer + * @param [in,out] len Pointer to data length + * + * @return true if the request was handled successfully + */ +static int usbd_standard_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + int rc = 0; + + switch (setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) { + case USB_REQUEST_RECIPIENT_DEVICE: + if (usbd_std_device_req_handler(setup, data, len) == false) { + rc = -1; + } + + break; + + case USB_REQUEST_RECIPIENT_INTERFACE: + if (usbd_std_interface_req_handler(setup, data, len) == false) { + rc = -1; + } + + break; + + case USB_REQUEST_RECIPIENT_ENDPOINT: + if (usbd_std_endpoint_req_handler(setup, data, len) == false) { + rc = -1; + } + + break; + + default: + rc = -1; + } + + return rc; +} + +/** + * @brief handler for class requests + * + * If a custom request handler was installed, this handler is called first. + * + * @param [in] setup The setup packet + * @param [in,out] data Data buffer + * @param [in,out] len Pointer to data length + * + * @return true if the request was handled successfully + */ +static int usbd_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USB_LOG_DBG("bRequest 0x%02x, wIndex 0x%04x\r\n", setup->bRequest, setup->wIndex); + + if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) != USB_REQUEST_RECIPIENT_INTERFACE) { + return -1; + } + + usb_slist_t *i, *j; + usb_slist_for_each(i, &usbd_class_head) + { + usbd_class_t *devclass = usb_slist_entry(i, struct usbd_class, list); + + usb_slist_for_each(j, &devclass->intf_list) + { + usbd_interface_t *intf = usb_slist_entry(j, struct usbd_interface, list); + + if (intf->class_handler && (intf->intf_num == (setup->wIndex & 0xFF))) { + return intf->class_handler(setup, data, len); + } + } + } + return -1; +} + +/** + * @brief handler for vendor requests + * + * If a custom request handler was installed, this handler is called first. + * + * @param [in] setup The setup packet + * @param [in,out] data Data buffer + * @param [in,out] len Pointer to data length + * + * @return true if the request was handled successfully + */ +static int usbd_vendor_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USB_LOG_DBG("bRequest 0x%02x, wValue0x%04x, wIndex 0x%04x\r\n", setup->bRequest, setup->wValue, setup->wIndex); + + // if((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) != USB_REQUEST_RECIPIENT_DEVICE) + // { + // return -1; + // } + + if (msosv1_desc) { + if (setup->bRequest == msosv1_desc->vendor_code) { + switch (setup->wIndex) { + case 0x04: + USB_LOG_INFO("get Compat ID\r\n"); + *data = (uint8_t *)msosv1_desc->compat_id; + *len = msosv1_desc->compat_id_len; + + return 0; + case 0x05: + USB_LOG_INFO("get Compat id properties\r\n"); + *data = (uint8_t *)msosv1_desc->comp_id_property; + *len = msosv1_desc->comp_id_property_len; + + return 0; + default: + USB_LOG_ERR("unknown vendor code\r\n"); + return -1; + } + } + } else if (msosv2_desc) { + if (setup->bRequest == msosv2_desc->vendor_code) { + switch (setup->wIndex) { + case WINUSB_REQUEST_GET_DESCRIPTOR_SET: + USB_LOG_INFO("GET MS OS 2.0 Descriptor\r\n"); + *data = (uint8_t *)msosv2_desc->compat_id; + *len = msosv2_desc->compat_id_len; + return 0; + default: + USB_LOG_ERR("unknown vendor code\r\n"); + return -1; + } + } + } + + usb_slist_t *i, *j; + + usb_slist_for_each(i, &usbd_class_head) + { + usbd_class_t *devclass = usb_slist_entry(i, struct usbd_class, list); + + usb_slist_for_each(j, &devclass->intf_list) + { + usbd_interface_t *intf = usb_slist_entry(j, struct usbd_interface, list); + + if (intf->vendor_handler && !intf->vendor_handler(setup, data, len)) { + return 0; + } + } + } + + return -1; +} + +/** + * @brief handler for special requests + * + * If a custom request handler was installed, this handler is called first. + * + * @param [in] setup The setup packet + * @param [in,out] data Data buffer + * @param [in,out] len Pointer to data length + * + * @return true if the request was handled successfully + */ +static int usbd_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + USB_LOG_DBG("bRequest 0x%02x, wIndex 0x%04x\r\n", setup->bRequest, setup->wIndex); + + if ((setup->bmRequestType & USB_REQUEST_RECIPIENT_MASK) != USB_REQUEST_RECIPIENT_INTERFACE) { + return -1; + } + + usb_slist_t *i, *j; + usb_slist_for_each(i, &usbd_class_head) + { + usbd_class_t *devclass = usb_slist_entry(i, struct usbd_class, list); + + usb_slist_for_each(j, &devclass->intf_list) + { + usbd_interface_t *intf = usb_slist_entry(j, struct usbd_interface, list); + + if (intf->custom_handler && (intf->intf_num == (setup->wIndex & 0xFF))) { + return intf->custom_handler(setup, data, len); + } + } + } + + return -1; +} + +/** + * @brief handle a request by calling one of the installed request handlers + * + * Local function to handle a request by calling one of the installed request + * handlers. In case of data going from host to device, the data is at *ppbData. + * In case of data going from device to host, the handler can either choose to + * write its data at *ppbData or update the data pointer. + * + * @param [in] setup The setup packet + * @param [in,out] data Data buffer + * @param [in,out] len Pointer to data length + * + * @return true if the request was handles successfully + */ +static bool usbd_setup_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len) +{ + uint8_t type = setup->bmRequestType & USB_REQUEST_TYPE_MASK; + + if (!usbd_custom_request_handler(setup, data, len)) { + return true; + } + + if (type == USB_REQUEST_STANDARD) { + if (usbd_standard_request_handler(setup, data, len) < 0) { + USB_LOG_ERR("Handler Error %d\r\n", type); + usbd_print_setup(setup); + return false; + } + } else if (type == USB_REQUEST_CLASS) { + if (usbd_class_request_handler(setup, data, len) < 0) { + USB_LOG_ERR("Handler Error %d\r\n", type); + usbd_print_setup(setup); + return false; + } + } else if (type == USB_REQUEST_VENDOR) { + if (usbd_vendor_request_handler(setup, data, len) < 0) { + USB_LOG_ERR("Handler Error %d\r\n", type); + usbd_print_setup(setup); + return false; + } + } else { + return false; + } + + return true; +} +/** + * @brief send data or status to host + * + * @return N/A + */ +static void usbd_send_to_host(uint16_t len) +{ + uint32_t chunk = 0U; + + if (usbd_core_cfg.zlp_flag == false) { + chunk = usbd_core_cfg.ep0_data_buf_residue; + + if (usbd_ep_write(USB_CONTROL_IN_EP0, usbd_core_cfg.ep0_data_buf, usbd_core_cfg.ep0_data_buf_residue, &chunk) < 0) { + USB_LOG_ERR("USB write data failed\r\n"); + return; + } + + usbd_core_cfg.ep0_data_buf += chunk; + usbd_core_cfg.ep0_data_buf_residue -= chunk; + + /* + * Set ZLP flag when host asks for a bigger length and the + * last chunk is wMaxPacketSize long, to indicate the last + * packet. + */ + if(!usbd_core_cfg.ep0_data_buf_residue && (len > usbd_core_cfg.ep0_data_buf_len) && !(usbd_core_cfg.ep0_data_buf_len % USB_CTRL_EP_MPS)){ + /* Transfers a zero-length packet next*/ + usbd_core_cfg.zlp_flag = true; + } + } else { + usbd_core_cfg.zlp_flag = false; + USB_LOG_DBG("send zlp\r\n"); + if (usbd_ep_write(USB_CONTROL_IN_EP0, NULL, 0, NULL) < 0) { + USB_LOG_ERR("USB write zlp failed\r\n"); + return; + } + } +} + +static void usbd_ep0_setup_handler(void) +{ + struct usb_setup_packet *setup = &usbd_core_cfg.setup; + + /* + * OUT transfer, Setup packet, + * reset request message state machine + */ + if (usbd_ep_read(USB_CONTROL_OUT_EP0, (uint8_t *)setup, + sizeof(struct usb_setup_packet), NULL) < 0) { + USB_LOG_ERR("Read Setup Packet failed\r\n"); + usbd_ep_set_stall(USB_CONTROL_IN_EP0); + return; + } + + //usbd_print_setup(setup); + + if (setup->wLength > USB_REQUEST_BUFFER_SIZE) { + if ((setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT) { + USB_LOG_ERR("Request buffer too small\r\n"); + usbd_ep_set_stall(USB_CONTROL_IN_EP0); + return; + } + } + + // usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data; + usbd_core_cfg.ep0_data_buf_residue = setup->wLength; + usbd_core_cfg.ep0_data_buf_len = setup->wLength; + usbd_core_cfg.zlp_flag = false; + + /* this maybe set code in class request code */ + if (setup->wLength && + (setup->bmRequestType & USB_REQUEST_DIR_MASK) == USB_REQUEST_DIR_OUT) { + USB_LOG_DBG("prepare to out data\r\n"); + return; + } + + /* Ask installed handler to process request */ + if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) { + USB_LOG_ERR("usbd_setup_request_handler failed\r\n"); + usbd_ep_set_stall(USB_CONTROL_IN_EP0); + return; + } + + /* Send smallest of requested and offered length */ + usbd_core_cfg.ep0_data_buf_residue = MIN(usbd_core_cfg.ep0_data_buf_len, + setup->wLength); + /*Send data or status to host*/ + usbd_send_to_host(setup->wLength); +} + +static void usbd_ep0_out_handler(void) +{ + uint32_t chunk = 0U; + struct usb_setup_packet *setup = &usbd_core_cfg.setup; + + /* OUT transfer, status packets */ + if (usbd_core_cfg.ep0_data_buf_residue == 0) { + /* absorb zero-length status message */ + USB_LOG_DBG("recv status\r\n"); + + if (usbd_ep_read(USB_CONTROL_OUT_EP0, + NULL, + 0, NULL) < 0) { + USB_LOG_ERR("Read DATA Packet failed\r\n"); + usbd_ep_set_stall(USB_CONTROL_IN_EP0); + } + + return; + } + + usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data; + + /* OUT transfer, data packets */ + if (usbd_ep_read(USB_CONTROL_OUT_EP0, + usbd_core_cfg.ep0_data_buf, + usbd_core_cfg.ep0_data_buf_residue, &chunk) < 0) { + USB_LOG_ERR("Read DATA Packet failed\r\n"); + usbd_ep_set_stall(USB_CONTROL_IN_EP0); + return; + } + + usbd_core_cfg.ep0_data_buf += chunk; + usbd_core_cfg.ep0_data_buf_residue -= chunk; + + if (usbd_core_cfg.ep0_data_buf_residue == 0) { + /* Received all, send data to handler */ + usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data; + + if (!usbd_setup_request_handler(setup, &usbd_core_cfg.ep0_data_buf, &usbd_core_cfg.ep0_data_buf_len)) { + USB_LOG_ERR("usbd_setup_request_handler1 failed\r\n"); + usbd_ep_set_stall(USB_CONTROL_IN_EP0); + return; + } + + /*Send status to host*/ + usbd_send_to_host(setup->wLength); + } else { + USB_LOG_ERR("ep0_data_buf_residue is not zero\r\n"); + } +} + +static void usbd_ep0_in_handler(void) +{ + struct usb_setup_packet *setup = &usbd_core_cfg.setup; + + /* Send more data if available */ + if (usbd_core_cfg.ep0_data_buf_residue != 0 || usbd_core_cfg.zlp_flag == true) { + usbd_send_to_host(setup->wLength); + } else { + /*ep0 tx has completed,and no data to send,so do nothing*/ + } +} + +static void usbd_ep_out_handler(uint8_t ep) +{ +#if USBD_EP_CALLBACK_SEARCH_METHOD == USBD_EP_CALLBACK_LIST_SEARCH + usb_slist_t *i, *j, *k; + usb_slist_for_each(i, &usbd_class_head) + { + usbd_class_t *devclass = usb_slist_entry(i, struct usbd_class, list); + + usb_slist_for_each(j, &devclass->intf_list) + { + usbd_interface_t *intf = usb_slist_entry(j, struct usbd_interface, list); + + usb_slist_for_each(k, &intf->ep_list) + { + usbd_endpoint_t *ept = usb_slist_entry(k, struct usbd_endpoint, list); + + if ((ept->ep_addr == ep) && ept->ep_cb) { + ept->ep_cb(ep); + } + } + } + } +#else + + if (usbd_core_cfg.out_ep_cb[ep & 0x7f]) { + usbd_core_cfg.out_ep_cb[ep & 0x7f](ep); + } + +#endif +} + +static void usbd_ep_in_handler(uint8_t ep) +{ +#if USBD_EP_CALLBACK_SEARCH_METHOD == USBD_EP_CALLBACK_LIST_SEARCH + usb_slist_t *i, *j, *k; + usb_slist_for_each(i, &usbd_class_head) + { + usbd_class_t *devclass = usb_slist_entry(i, struct usbd_class, list); + + usb_slist_for_each(j, &devclass->intf_list) + { + usbd_interface_t *intf = usb_slist_entry(j, struct usbd_interface, list); + + usb_slist_for_each(k, &intf->ep_list) + { + usbd_endpoint_t *ept = usb_slist_entry(k, struct usbd_endpoint, list); + + if ((ept->ep_addr == ep) && ept->ep_cb) { + ept->ep_cb(ep); + } + } + } + } +#else + + if (usbd_core_cfg.in_ep_cb[ep & 0x7f]) { + usbd_core_cfg.in_ep_cb[ep & 0x7f](ep); + } + +#endif +} + +static void usbd_class_event_notify_handler(uint8_t event, void *arg) +{ + usb_slist_t *i, *j; + usb_slist_for_each(i, &usbd_class_head) + { + usbd_class_t *devclass = usb_slist_entry(i, struct usbd_class, list); + + usb_slist_for_each(j, &devclass->intf_list) + { + usbd_interface_t *intf = usb_slist_entry(j, struct usbd_interface, list); + + if (intf->notify_handler) { + intf->notify_handler(event, arg); + } + } + } +} + +void usbd_event_notify_handler(uint8_t event, void *arg) +{ + switch (event) { + case USBD_EVENT_RESET: + usbd_set_address(0); + usbd_core_cfg.configured = 0; + usbd_core_cfg.configuration = 0; + struct usbd_endpoint_cfg ep0_cfg; + ep0_cfg.ep_mps = USB_CTRL_EP_MPS; + ep0_cfg.ep_type = USBD_EP_TYPE_CTRL; + ep0_cfg.ep_addr = USB_CONTROL_IN_EP0; + /*set USB_CONTROL_IN_EP0 nak*/ + usbd_ep_open(&ep0_cfg); + + ep0_cfg.ep_addr = USB_CONTROL_OUT_EP0; + /*set USB_CONTROL_OUT_EP0 ack to prepare receiving setup data*/ + usbd_ep_open(&ep0_cfg); +#if USBD_EP_CALLBACK_SEARCH_METHOD == USBD_EP_CALLBACK_ARR_SEARCH + usbd_ep_callback_register(); +#endif + + case USBD_EVENT_ERROR: + case USBD_EVENT_SOF: + case USBD_EVENT_CONNECTED: + case USBD_EVENT_CONFIGURED: + case USBD_EVENT_SUSPEND: + case USBD_EVENT_DISCONNECTED: + case USBD_EVENT_RESUME: + case USBD_EVENT_SET_INTERFACE: + case USBD_EVENT_SET_REMOTE_WAKEUP: + case USBD_EVENT_CLEAR_REMOTE_WAKEUP: + case USBD_EVENT_SET_HALT: + case USBD_EVENT_CLEAR_HALT: + usbd_class_event_notify_handler(event, arg); + break; + + case USBD_EVENT_SETUP_NOTIFY: + usbd_ep0_setup_handler(); + break; + + case USBD_EVENT_EP0_IN_NOTIFY: + usbd_ep0_in_handler(); + break; + + case USBD_EVENT_EP0_OUT_NOTIFY: + usbd_ep0_out_handler(); + break; + + case USBD_EVENT_EP_IN_NOTIFY: + usbd_ep_in_handler((uint32_t)arg); + break; + + case USBD_EVENT_EP_OUT_NOTIFY: + usbd_ep_out_handler((uint32_t)arg); + break; + + default: + USB_LOG_ERR("USB unknown event: %d\r\n", event); + break; + } +} + +void usbd_desc_register(const uint8_t *desc) +{ + usbd_core_cfg.descriptors = desc; +} +/* Register MS OS Descriptors version 1 */ +void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc) +{ + msosv1_desc = desc; +} + +/* Register MS OS Descriptors version 2 */ +void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc) +{ + msosv2_desc = desc; +} + +void usbd_bos_desc_register(struct usb_bos_descriptor *desc) +{ + bos_desc = desc; +} + +void usbd_class_register(usbd_class_t *devclass) +{ + usb_slist_add_tail(&usbd_class_head, &devclass->list); + usb_slist_init(&devclass->intf_list); +} + +void usbd_class_add_interface(usbd_class_t *devclass, usbd_interface_t *intf) +{ + static uint8_t intf_offset = 0; + intf->intf_num = intf_offset; + usb_slist_add_tail(&devclass->intf_list, &intf->list); + usb_slist_init(&intf->ep_list); + intf_offset++; +} + +void usbd_interface_add_endpoint(usbd_interface_t *intf, usbd_endpoint_t *ep) +{ + usb_slist_add_tail(&intf->ep_list, &ep->list); +} + +bool usb_device_is_configured(void) +{ + return usbd_core_cfg.configured; +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbd_core.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbd_core.h new file mode 100644 index 00000000..8213008a --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbd_core.h @@ -0,0 +1,138 @@ +/** + * @file usbd_core.h + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBD_CORE_H +#define _USBD_CORE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "usb_util.h" +#include "usb_def.h" +#include "usb_dc.h" + +enum usbd_event_type { + /** USB error reported by the controller */ + USBD_EVENT_ERROR, + /** USB reset */ + USBD_EVENT_RESET, + /** Start of Frame received */ + USBD_EVENT_SOF, + /** USB connection established, hardware enumeration is completed */ + USBD_EVENT_CONNECTED, + /** USB configuration done */ + USBD_EVENT_CONFIGURED, + /** USB connection suspended by the HOST */ + USBD_EVENT_SUSPEND, + /** USB connection lost */ + USBD_EVENT_DISCONNECTED, + /** USB connection resumed by the HOST */ + USBD_EVENT_RESUME, + + /** USB interface selected */ + USBD_EVENT_SET_INTERFACE, + /** USB interface selected */ + USBD_EVENT_SET_REMOTE_WAKEUP, + /** USB interface selected */ + USBD_EVENT_CLEAR_REMOTE_WAKEUP, + /** Set Feature ENDPOINT_HALT received */ + USBD_EVENT_SET_HALT, + /** Clear Feature ENDPOINT_HALT received */ + USBD_EVENT_CLEAR_HALT, + /** setup packet received */ + USBD_EVENT_SETUP_NOTIFY, + /** ep0 in packet received */ + USBD_EVENT_EP0_IN_NOTIFY, + /** ep0 out packet received */ + USBD_EVENT_EP0_OUT_NOTIFY, + /** ep in packet except ep0 received */ + USBD_EVENT_EP_IN_NOTIFY, + /** ep out packet except ep0 received */ + USBD_EVENT_EP_OUT_NOTIFY, + /** Initial USB connection status */ + USBD_EVENT_UNKNOWN +}; + +/** + * @brief Callback function signature for the USB Endpoint status + */ +typedef void (*usbd_endpoint_callback)(uint8_t ep); + +/** + * @brief Callback function signature for class specific requests + * + * Function which handles Class specific requests corresponding to an + * interface number specified in the device descriptor table. For host + * to device direction the 'len' and 'payload_data' contain the length + * of the received data and the pointer to the received data respectively. + * For device to host class requests, 'len' and 'payload_data' should be + * set by the callback function with the length and the address of the + * data to be transmitted buffer respectively. + */ +typedef int (*usbd_request_handler)(struct usb_setup_packet *setup, + uint8_t **data, uint32_t *transfer_len); + +/* callback function pointer structure for Application to handle events */ +typedef void (*usbd_notify_handler)(uint8_t event, void *arg); + +typedef struct usbd_endpoint { + usb_slist_t list; + uint8_t ep_addr; + usbd_endpoint_callback ep_cb; +} usbd_endpoint_t; + +typedef struct usbd_interface { + usb_slist_t list; + /** Handler for USB Class specific commands*/ + usbd_request_handler class_handler; + /** Handler for USB Vendor specific commands */ + usbd_request_handler vendor_handler; + /** Handler for USB custom specific commands */ + usbd_request_handler custom_handler; + /** Handler for USB event notify commands */ + usbd_notify_handler notify_handler; + uint8_t intf_num; + usb_slist_t ep_list; +} usbd_interface_t; + +typedef struct usbd_class { + usb_slist_t list; + const char *name; + usb_slist_t intf_list; +} usbd_class_t; + +void usbd_event_notify_handler(uint8_t event, void *arg); + +void usbd_desc_register(const uint8_t *desc); +void usbd_class_register(usbd_class_t *devclass); +void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc); +void usbd_msosv2_desc_register(struct usb_msosv2_descriptor *desc); +void usbd_bos_desc_register(struct usb_bos_descriptor *desc); +void usbd_class_add_interface(usbd_class_t *devclass, usbd_interface_t *intf); +void usbd_interface_add_endpoint(usbd_interface_t *intf, usbd_endpoint_t *ep); +bool usb_device_is_configured(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbh_core.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbh_core.c new file mode 100644 index 00000000..7fa335b7 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbh_core.c @@ -0,0 +1,990 @@ +/** + * @file usbh_core.c + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#include "usbh_core.h" +#include "usbh_cdc_acm.h" +#include "usbh_hid.h" +#include "usbh_msc.h" + +static const char *speed_table[] = { "error speed", "low speed", "full speed", "high speed" }; + +static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subcalss, uint8_t protocol, uint16_t vid, uint16_t pid); +void usbh_hport_activate(struct usbh_hubport *hport); +void usbh_hport_deactivate(struct usbh_hubport *hport); + +/* general descriptor field offsets */ +#define DESC_bLength 0 /** Length offset */ +#define DESC_bDescriptorType 1 /** Descriptor type offset */ + +#define USB_DEV_ADDR_MAX 0x7f +#define USB_DEV_ADDR_MARK_OFFSET 5 +#define USB_DEV_ADDR_MARK_MASK 0x1f + +struct usbh_devaddr_priv { + /** + * alloctab[0]:addr from 0~31 + * alloctab[1]:addr from 32~63 + * alloctab[2]:addr from 64~95 + * alloctab[3]:addr from 96~127 + * + */ + uint8_t next; /* Next device address */ + uint32_t alloctab[4]; /* Bit allocation table */ +}; + +struct usbh_roothubport_priv { + struct usbh_hubport hport; /* Common hub port definitions */ + struct usbh_devaddr_priv devgen; /* Address generation data */ +}; + +struct usbh_core_priv { + struct usbh_roothubport_priv rhport[CONFIG_USBHOST_RHPORTS]; + volatile struct usbh_hubport *active_hport; /* Used to pass external hub port events */ + volatile bool pscwait; /* TRUE: Thread is waiting for port status change event */ + usb_osal_sem_t pscsem; /* Semaphore to wait for a port event */ +} usbh_core_cfg; + +static inline struct usbh_roothubport_priv *usbh_find_roothub_port(struct usbh_hubport *hport) +{ + while (hport->parent != NULL) { + hport = hport->parent->parent; + } + return (struct usbh_roothubport_priv *)hport; +} + +static int usbh_allocate_devaddr(struct usbh_devaddr_priv *devgen) +{ + uint8_t startaddr = devgen->next; + uint8_t devaddr; + int index; + int bitno; + + /* Loop until we find a valid device address */ + + for (;;) { + /* Try the next device address */ + + devaddr = devgen->next; + if (devgen->next >= 0x7f) { + devgen->next = 1; + } else { + devgen->next++; + } + + /* Is this address already allocated? */ + + index = devaddr >> 5; + bitno = devaddr & 0x1f; + if ((devgen->alloctab[index] & (1 << bitno)) == 0) { + /* No... allocate it now */ + + devgen->alloctab[index] |= (1 << bitno); + return (int)devaddr; + } + + /* This address has already been allocated. The following logic will + * prevent (unexpected) infinite loops. + */ + + if (startaddr == devaddr) { + /* We are back where we started... the are no free device address */ + + return -ENOMEM; + } + } +} + +static int usbh_free_devaddr(struct usbh_devaddr_priv *devgen, uint8_t devaddr) +{ + int index; + int bitno; + + if ((devaddr > 0) && (devaddr < USB_DEV_ADDR_MAX)) { + index = devaddr >> USB_DEV_ADDR_MARK_OFFSET; + bitno = devaddr & USB_DEV_ADDR_MARK_MASK; + + /* Free the address by clearing the associated bit in the alloctab[]; */ + if ((devgen->alloctab[index] |= (1 << bitno)) != 0) { + devgen->alloctab[index] &= ~(1 << bitno); + } else { + return -1; + } + /* Reset the next pointer if the one just released has a lower value */ + + if (devaddr < devgen->next) { + devgen->next = devaddr; + } + } + + return 0; +} + +static int usbh_devaddr_create(struct usbh_hubport *hport) +{ + struct usbh_roothubport_priv *rhport; + rhport = usbh_find_roothub_port(hport); + + return usbh_allocate_devaddr(&rhport->devgen); +} + +static int usbh_devaddr_destroy(struct usbh_hubport *hport, uint8_t dev_addr) +{ + struct usbh_roothubport_priv *rhport; + rhport = usbh_find_roothub_port(hport); + + return usbh_free_devaddr(&rhport->devgen, dev_addr); +} + +static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device_descriptor *desc, uint16_t length) +{ + if (desc->bLength != USB_SIZEOF_DEVICE_DESC) { + USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength); + return -EINVAL; + } else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_DEVICE) { + USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType); + return -EINVAL; + } else { + if (length <= 8) { + return 0; + } +#if 0 + USB_LOG_DBG("Device Descriptor:\r\n"); + USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength); + USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType); + USB_LOG_DBG("bcdUSB: 0x%04x \r\n", desc->bcdUSB); + USB_LOG_DBG("bDeviceClass: 0x%02x \r\n", desc->bDeviceClass); + USB_LOG_DBG("bDeviceSubClass: 0x%02x \r\n", desc->bDeviceSubClass); + USB_LOG_DBG("bDeviceProtocol: 0x%02x \r\n", desc->bDeviceProtocol); + USB_LOG_DBG("bMaxPacketSize0: 0x%02x \r\n", desc->bMaxPacketSize0); + USB_LOG_DBG("idVendor: 0x%04x \r\n", desc->idVendor); + USB_LOG_DBG("idProduct: 0x%04x \r\n", desc->idProduct); + USB_LOG_DBG("bcdDevice: 0x%04x \r\n", desc->bcdDevice); + USB_LOG_DBG("iManufacturer: 0x%02x \r\n", desc->iManufacturer); + USB_LOG_DBG("iProduct: 0x%02x \r\n", desc->iProduct); + USB_LOG_DBG("iSerialNumber: 0x%02x \r\n", desc->iSerialNumber); + USB_LOG_DBG("bNumConfigurations: 0x%02x\r\n", desc->bNumConfigurations); +#endif + hport->device_desc.bLength = desc->bLength; + hport->device_desc.bDescriptorType = desc->bDescriptorType; + hport->device_desc.bcdUSB = desc->bcdUSB; + hport->device_desc.bDeviceClass = desc->bDeviceClass; + hport->device_desc.bDeviceSubClass = desc->bDeviceSubClass; + hport->device_desc.bDeviceProtocol = desc->bDeviceProtocol; + hport->device_desc.bMaxPacketSize0 = desc->bMaxPacketSize0; + hport->device_desc.idVendor = desc->idVendor; + hport->device_desc.idProduct = desc->idProduct; + hport->device_desc.bcdDevice = desc->bcdDevice; + hport->device_desc.iManufacturer = desc->iManufacturer; + hport->device_desc.iProduct = desc->iProduct; + hport->device_desc.iSerialNumber = desc->iSerialNumber; + hport->device_desc.bNumConfigurations = desc->bNumConfigurations; + } + return 0; +} + +static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_configuration_descriptor *desc, uint16_t length) +{ + uint32_t total_len = 0; + uint8_t ep_num = 0; + uint8_t intf_num = 0; + uint8_t *p = (uint8_t *)desc; + if (desc->bLength != USB_SIZEOF_CONFIG_DESC) { + USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength); + return -EINVAL; + } else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_CONFIGURATION) { + USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType); + return -EINVAL; + } else { + if (length <= USB_SIZEOF_CONFIG_DESC) { + return 0; + } +#if 0 + USB_LOG_DBG("Config Descriptor:\r\n"); + USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength); + USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType); + USB_LOG_DBG("wTotalLength: 0x%04x \r\n", desc->wTotalLength); + USB_LOG_DBG("bNumInterfaces: 0x%02x \r\n", desc->bNumInterfaces); + USB_LOG_DBG("bConfigurationValue: 0x%02x \r\n", desc->bConfigurationValue); + USB_LOG_DBG("iConfiguration: 0x%02x \r\n", desc->iConfiguration); + USB_LOG_DBG("bmAttributes: 0x%02x \r\n", desc->bmAttributes); + USB_LOG_DBG("bMaxPower: 0x%02x \r\n", desc->bMaxPower); +#endif + hport->config.config_desc.bLength = desc->bLength; + hport->config.config_desc.bDescriptorType = desc->bDescriptorType; + hport->config.config_desc.wTotalLength = desc->wTotalLength; + hport->config.config_desc.bNumInterfaces = desc->bNumInterfaces; + hport->config.config_desc.bConfigurationValue = desc->bConfigurationValue; + hport->config.config_desc.iConfiguration = desc->iConfiguration; + hport->config.config_desc.iConfiguration = desc->iConfiguration; + hport->config.config_desc.bmAttributes = desc->bmAttributes; + hport->config.config_desc.bMaxPower = desc->bMaxPower; + + if (length > USB_SIZEOF_CONFIG_DESC) { + while (p[DESC_bLength] && (total_len < desc->wTotalLength) && (intf_num < desc->bNumInterfaces)) { + p += p[DESC_bLength]; + total_len += p[DESC_bLength]; + if (p[DESC_bDescriptorType] == USB_DESCRIPTOR_TYPE_INTERFACE) { + struct usb_interface_descriptor *intf_desc = (struct usb_interface_descriptor *)p; +#if 0 + USB_LOG_DBG("Interface Descriptor:\r\n"); + USB_LOG_DBG("bLength: 0x%02x \r\n", intf_desc->bLength); + USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", intf_desc->bDescriptorType); + USB_LOG_DBG("bInterfaceNumber: 0x%02x \r\n", intf_desc->bInterfaceNumber); + USB_LOG_DBG("bAlternateSetting: 0x%02x \r\n", intf_desc->bAlternateSetting); + USB_LOG_DBG("bNumEndpoints: 0x%02x \r\n", intf_desc->bNumEndpoints); + USB_LOG_DBG("bInterfaceClass: 0x%02x \r\n", intf_desc->bInterfaceClass); + USB_LOG_DBG("bInterfaceSubClass: 0x%02x \r\n", intf_desc->bInterfaceSubClass); + USB_LOG_DBG("bInterfaceProtocol: 0x%02x \r\n", intf_desc->bInterfaceProtocol); + USB_LOG_DBG("iInterface: 0x%02x \r\n", intf_desc->iInterface); +#endif + memset(&hport->config.intf[intf_num], 0, sizeof(struct usbh_interface)); + + hport->config.intf[intf_num].intf_desc.bLength = intf_desc->bLength; + hport->config.intf[intf_num].intf_desc.bDescriptorType = intf_desc->bDescriptorType; + hport->config.intf[intf_num].intf_desc.bInterfaceNumber = intf_desc->bInterfaceNumber; + hport->config.intf[intf_num].intf_desc.bAlternateSetting = intf_desc->bAlternateSetting; + hport->config.intf[intf_num].intf_desc.bNumEndpoints = intf_desc->bNumEndpoints; + hport->config.intf[intf_num].intf_desc.bInterfaceClass = intf_desc->bInterfaceClass; + hport->config.intf[intf_num].intf_desc.bInterfaceSubClass = intf_desc->bInterfaceSubClass; + hport->config.intf[intf_num].intf_desc.bInterfaceProtocol = intf_desc->bInterfaceProtocol; + hport->config.intf[intf_num].intf_desc.iInterface = intf_desc->iInterface; + ep_num = 0; + while (p[DESC_bLength] && (total_len < desc->wTotalLength) && (ep_num < intf_desc->bNumEndpoints)) { + p += p[DESC_bLength]; + total_len += p[DESC_bLength]; + if (p[DESC_bDescriptorType] == USB_DESCRIPTOR_TYPE_ENDPOINT) { + struct usb_endpoint_descriptor *ep_desc = (struct usb_endpoint_descriptor *)p; +#if 0 + USB_LOG_DBG("Endpoint Descriptor:\r\n"); + USB_LOG_DBG("bLength: 0x%02x \r\n", ep_desc->bLength); + USB_LOG_DBG("bDescriptorType: 0x%02x \r\n", ep_desc->bDescriptorType); + USB_LOG_DBG("bEndpointAddress: 0x%02x \r\n", ep_desc->bEndpointAddress); + USB_LOG_DBG("bmAttributes: 0x%02x \r\n", ep_desc->bmAttributes); + USB_LOG_DBG("wMaxPacketSize: 0x%04x \r\n", ep_desc->wMaxPacketSize); + USB_LOG_DBG("bInterval: 0x%02x \r\n", ep_desc->bInterval); +#endif + memset(&hport->config.intf[intf_num].ep[ep_num], 0, sizeof(struct usbh_endpoint)); + + hport->config.intf[intf_num].ep[ep_num].ep_desc.bLength = ep_desc->bLength; + hport->config.intf[intf_num].ep[ep_num].ep_desc.bDescriptorType = ep_desc->bDescriptorType; + hport->config.intf[intf_num].ep[ep_num].ep_desc.bEndpointAddress = ep_desc->bEndpointAddress; + hport->config.intf[intf_num].ep[ep_num].ep_desc.bmAttributes = ep_desc->bmAttributes; + hport->config.intf[intf_num].ep[ep_num].ep_desc.wMaxPacketSize = ep_desc->wMaxPacketSize; + hport->config.intf[intf_num].ep[ep_num].ep_desc.bInterval = ep_desc->bInterval; + ep_num++; + } + } + intf_num++; + } + } + } + } + return 0; +} +#if 0 +static int parse_string_descriptor(struct usbh_hubport *hport, struct usb_string_descriptor *desc, uint8_t str_idx, uint16_t length) +{ + uint8_t string[64 + 1] = { 0 }; + uint8_t *p = (uint8_t *)desc; + + if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_STRING) { + USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType); + return -2; + } else { + p += 2; + for (uint32_t i = 0; i < (desc->bLength - 2) / 2; i++) { + string[i] = *p; + p += 2; + } + USB_LOG_DBG("string:%s\r\n", string); + } + return 0; +} +#endif + +static void usbh_print_hubport_info(struct usbh_hubport *hport) +{ + printf("Device Descriptor:\r\n"); + printf("bLength: 0x%02x \r\n", hport->device_desc.bLength); + printf("bDescriptorType: 0x%02x \r\n", hport->device_desc.bDescriptorType); + printf("bcdUSB: 0x%04x \r\n", hport->device_desc.bcdUSB); + printf("bDeviceClass: 0x%02x \r\n", hport->device_desc.bDeviceClass); + printf("bDeviceSubClass: 0x%02x \r\n", hport->device_desc.bDeviceSubClass); + printf("bDeviceProtocol: 0x%02x \r\n", hport->device_desc.bDeviceProtocol); + printf("bMaxPacketSize0: 0x%02x \r\n", hport->device_desc.bMaxPacketSize0); + printf("idVendor: 0x%04x \r\n", hport->device_desc.idVendor); + printf("idProduct: 0x%04x \r\n", hport->device_desc.idProduct); + printf("bcdDevice: 0x%04x \r\n", hport->device_desc.bcdDevice); + printf("iManufacturer: 0x%02x \r\n", hport->device_desc.iManufacturer); + printf("iProduct: 0x%02x \r\n", hport->device_desc.iProduct); + printf("iSerialNumber: 0x%02x \r\n", hport->device_desc.iSerialNumber); + printf("bNumConfigurations: 0x%02x\r\n", hport->device_desc.bNumConfigurations); + + printf("Config Descriptor:\r\n"); + printf("bLength: 0x%02x \r\n", hport->config.config_desc.bLength); + printf("bDescriptorType: 0x%02x \r\n", hport->config.config_desc.bDescriptorType); + printf("wTotalLength: 0x%04x \r\n", hport->config.config_desc.wTotalLength); + printf("bNumInterfaces: 0x%02x \r\n", hport->config.config_desc.bNumInterfaces); + printf("bConfigurationValue: 0x%02x \r\n", hport->config.config_desc.bConfigurationValue); + printf("iConfiguration: 0x%02x \r\n", hport->config.config_desc.iConfiguration); + printf("bmAttributes: 0x%02x \r\n", hport->config.config_desc.bmAttributes); + printf("bMaxPower: 0x%02x \r\n", hport->config.config_desc.bMaxPower); + + for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) { + printf("Interface Descriptor:\r\n"); + printf("bLength: 0x%02x \r\n", hport->config.intf[i].intf_desc.bLength); + printf("bDescriptorType: 0x%02x \r\n", hport->config.intf[i].intf_desc.bDescriptorType); + printf("bInterfaceNumber: 0x%02x \r\n", hport->config.intf[i].intf_desc.bInterfaceNumber); + printf("bAlternateSetting: 0x%02x \r\n", hport->config.intf[i].intf_desc.bAlternateSetting); + printf("bNumEndpoints: 0x%02x \r\n", hport->config.intf[i].intf_desc.bNumEndpoints); + printf("bInterfaceClass: 0x%02x \r\n", hport->config.intf[i].intf_desc.bInterfaceClass); + printf("bInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].intf_desc.bInterfaceSubClass); + printf("bInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].intf_desc.bInterfaceProtocol); + printf("iInterface: 0x%02x \r\n", hport->config.intf[i].intf_desc.iInterface); + + for (uint8_t j = 0; j < hport->config.intf[i].intf_desc.bNumEndpoints; j++) { + printf("Endpoint Descriptor:\r\n"); + printf("bLength: 0x%02x \r\n", hport->config.intf[i].ep[j].ep_desc.bLength); + printf("bDescriptorType: 0x%02x \r\n", hport->config.intf[i].ep[j].ep_desc.bDescriptorType); + printf("bEndpointAddress: 0x%02x \r\n", hport->config.intf[i].ep[j].ep_desc.bEndpointAddress); + printf("bmAttributes: 0x%02x \r\n", hport->config.intf[i].ep[j].ep_desc.bmAttributes); + printf("wMaxPacketSize: 0x%04x \r\n", hport->config.intf[i].ep[j].ep_desc.wMaxPacketSize); + printf("bInterval: 0x%02x \r\n", hport->config.intf[i].ep[j].ep_desc.bInterval); + } + } +} + +static int usbh_enumerate(struct usbh_hubport *hport) +{ + struct usb_interface_descriptor *intf_desc; + struct usb_setup_packet *setup; + uint8_t *ep0_buffer; + uint8_t descsize; + int dev_addr; + uint8_t ep_mps; + int ret; + +#define USB_REQUEST_BUFFER_SIZE 256 + /* Allocate buffer for setup and data buffer */ + setup = usb_iomalloc(sizeof(struct usb_setup_packet)); + if (setup == NULL) { + USB_LOG_ERR("Fail to alloc setup\r\n"); + return -ENOMEM; + } + + ep0_buffer = usb_iomalloc(USB_REQUEST_BUFFER_SIZE); + if (ep0_buffer == NULL) { + USB_LOG_ERR("Fail to alloc ep0_buffer\r\n"); + return -ENOMEM; + } + + /* Pick an appropriate packet size for this device + * + * USB 2.0, Paragraph 5.5.3 "Control Transfer Packet Size Constraints" + * + * "An endpoint for control transfers specifies the maximum data + * payload size that the endpoint can accept from or transmit to + * the bus. The allowable maximum control transfer data payload + * sizes for full-speed devices is 8, 16, 32, or 64 bytes; for + * high-speed devices, it is 64 bytes and for low-speed devices, + * it is 8 bytes. This maximum applies to the data payloads of the + * Data packets following a Setup..." + */ + + if (hport->speed == USB_SPEED_HIGH) { + /* For high-speed, we must use 64 bytes */ + ep_mps = 64; + descsize = USB_SIZEOF_DEVICE_DESC; + } else { + /* Eight will work for both low- and full-speed */ + ep_mps = 8; + descsize = 8; + } + + /* Configure EP0 with the initial maximum packet size */ + usbh_ep0_reconfigure(hport->ep0, 0, ep_mps, hport->speed); + + /* Read the first 8 bytes of the device descriptor */ + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; + setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0); + setup->wIndex = 0; + setup->wLength = descsize; + + ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + if (ret < 0) { + USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret); + goto errout; + } + + parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_buffer, descsize); + + /* Extract the correct max packetsize from the device descriptor */ + ep_mps = ((struct usb_device_descriptor *)ep0_buffer)->bMaxPacketSize0; + + /* And reconfigure EP0 with the correct maximum packet size */ + usbh_ep0_reconfigure(hport->ep0, 0, ep_mps, hport->speed); + + /* Assign a function address to the device connected to this port */ + dev_addr = usbh_devaddr_create(hport); + if (dev_addr < 0) { + USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret); + goto errout; + } + + /* Set the USB device address */ + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = USB_REQUEST_SET_ADDRESS; + setup->wValue = dev_addr; + setup->wIndex = 0; + setup->wLength = 0; + + ret = usbh_control_transfer(hport->ep0, setup, NULL); + if (ret < 0) { + USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret); + goto errout; + } + + /* wait device address set completely */ + usb_osal_msleep(2); + + /* Assign the function address to the port */ + hport->dev_addr = dev_addr; + + /* And reconfigure EP0 with the correct address */ + usbh_ep0_reconfigure(hport->ep0, dev_addr, ep_mps, hport->speed); + + /* Read the full device descriptor if hport is not in high speed*/ + if (descsize < USB_SIZEOF_DEVICE_DESC) { + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; + setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0); + setup->wIndex = 0; + setup->wLength = USB_SIZEOF_DEVICE_DESC; + + ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + if (ret < 0) { + USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret); + goto errout; + } + + parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_buffer, USB_SIZEOF_DEVICE_DESC); + } + + /* Read the first 9 bytes of the config descriptor */ + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; + setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | 0); + setup->wIndex = 0; + setup->wLength = USB_SIZEOF_CONFIG_DESC; + + ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + if (ret < 0) { + USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret); + goto errout; + } + + parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_buffer, USB_SIZEOF_CONFIG_DESC); + + /* Read the full size of the configuration data */ + uint16_t wTotalLength = ((struct usb_configuration_descriptor *)ep0_buffer)->wTotalLength; + + setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = USB_REQUEST_GET_DESCRIPTOR; + setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | 0); + setup->wIndex = 0; + setup->wLength = wTotalLength; + + ret = usbh_control_transfer(hport->ep0, setup, ep0_buffer); + if (ret < 0) { + USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret); + goto errout; + } + + parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_buffer, wTotalLength); + + /* Select device configuration 1 */ + setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE; + setup->bRequest = USB_REQUEST_SET_CONFIGURATION; + setup->wValue = 1; + setup->wIndex = 0; + setup->wLength = 0; + + ret = usbh_control_transfer(hport->ep0, setup, NULL); + if (ret < 0) { + USB_LOG_ERR("Failed to set configuration,errorcode:%d\r\n", ret); + goto errout; + } + + USB_LOG_INFO("Enumeration success, start loading class driver\r\n"); + /*search supported class driver*/ + for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) { + intf_desc = &hport->config.intf[i].intf_desc; + + struct usbh_class_driver *class_driver = (struct usbh_class_driver *)usbh_find_class_driver(intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol, hport->device_desc.idVendor, hport->device_desc.idProduct); + + if (class_driver == NULL) { + USB_LOG_ERR("do not support Class:0x%02x,Subclass:0x%02x,Protocl:0x%02x\r\n", + intf_desc->bInterfaceClass, + intf_desc->bInterfaceSubClass, + intf_desc->bInterfaceProtocol); + + continue; + } + hport->config.intf[i].class_driver = class_driver; + + if (hport->config.intf[i].class_driver->connect) { + ret = CLASS_CONNECT(hport, i); + if (ret < 0) { + ret = CLASS_DISCONNECT(hport, i); + goto errout; + } + } + } + +errout: + if (ret < 0) { + usbh_hport_deactivate(hport); + } + + if (setup) { + usb_iofree(setup); + } + if (ep0_buffer) { + usb_iofree(ep0_buffer); + } + + return ret; +} + +static int usbh_portchange_wait(struct usbh_hubport **hport) +{ + struct usbh_hubport *connport = NULL; + uint32_t flags; + int ret; + + /* Loop until a change in connection state is detected */ + while (1) { + /* Check for a change in the connection state on any root hub port */ + flags = usb_osal_enter_critical_section(); + for (uint8_t port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { + connport = &usbh_core_cfg.rhport[port - 1].hport; + + if (connport->port_change) { + connport->port_change = false; + *hport = connport; + usb_osal_leave_critical_section(flags); + return 0; + } + } + /* Is a device connected to an external hub? */ + if (usbh_core_cfg.active_hport) { + connport = (struct usbh_hubport *)usbh_core_cfg.active_hport; + usbh_core_cfg.active_hport = NULL; + *hport = connport; + usb_osal_leave_critical_section(flags); + return 0; + } + /* No changes on any port. Wait for a connection/disconnection event and check again */ + usbh_core_cfg.pscwait = true; + usb_osal_leave_critical_section(flags); + ret = usb_osal_sem_take(usbh_core_cfg.pscsem); + if (ret < 0) { + return ret; + } + } +} + +static void usbh_portchange_detect_thread(void *argument) +{ + struct usbh_hubport *hport = NULL; + uint32_t flags; + + flags = usb_osal_enter_critical_section(); + usb_hc_init(); + + for (uint8_t port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { + usbh_core_cfg.rhport[port - 1].hport.port = port; + usbh_core_cfg.rhport[port - 1].devgen.next = 1; + usbh_hport_activate(&usbh_core_cfg.rhport[port - 1].hport); + } + + usb_osal_leave_critical_section(flags); + + while (1) { + usbh_portchange_wait(&hport); + if (hport->connected) { + /*if roothub port,reset port first*/ + if (ROOTHUB(hport)) { + /* Reset the host port */ + usbh_reset_port(hport->port); + usb_osal_msleep(200); + /* Get the current device speed */ + hport->speed = usbh_get_port_speed(hport->port); + USB_LOG_INFO("Bus %u, Port %u connected, %s\r\n", 1, hport->port, speed_table[hport->speed]); + } else { + USB_LOG_INFO("Bus %u, Port %u connected, %s\r\n", hport->parent->index, hport->port, speed_table[hport->speed]); + } + usb_osal_thread_suspend(g_lpworkq.thread); + usbh_enumerate(hport); + usb_osal_thread_resume(g_lpworkq.thread); + } else { + usbh_hport_deactivate(hport); + for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) { + if (hport->config.intf[i].class_driver && hport->config.intf[i].class_driver->disconnect) { + CLASS_DISCONNECT(hport, i); + } + } + + hport->config.config_desc.bNumInterfaces = 0; + + if (ROOTHUB(hport)) { + USB_LOG_INFO("Bus %u,Port:%u disconnected\r\n", 1, hport->port); + } else { + USB_LOG_INFO("Bus %u,Port:%u disconnected\r\n", hport->parent->index, hport->port); + } + } + } +} + +void usbh_external_hport_connect(struct usbh_hubport *hport) +{ + uint32_t flags; + + usbh_hport_activate(hport); + + flags = usb_osal_enter_critical_section(); + + hport->connected = true; + usbh_core_cfg.active_hport = hport; + + if (usbh_core_cfg.pscwait) { + usbh_core_cfg.pscwait = false; + usb_osal_sem_give(usbh_core_cfg.pscsem); + } + + usb_osal_leave_critical_section(flags); +} + +void usbh_external_hport_disconnect(struct usbh_hubport *hport) +{ + uint32_t flags; + + flags = usb_osal_enter_critical_section(); + hport->connected = false; + usbh_core_cfg.active_hport = hport; + + if (usbh_core_cfg.pscwait) { + usbh_core_cfg.pscwait = false; + usb_osal_sem_give(usbh_core_cfg.pscsem); + } + + usb_osal_leave_critical_section(flags); +} + +void usbh_hport_activate(struct usbh_hubport *hport) +{ + struct usbh_endpoint_cfg ep0_cfg; + uint32_t flags; + + flags = usb_osal_enter_critical_section(); + memset(&ep0_cfg, 0, sizeof(struct usbh_endpoint_cfg)); + + ep0_cfg.ep_addr = 0x00; + ep0_cfg.ep_interval = 0x00; + ep0_cfg.ep_mps = 0x08; + ep0_cfg.ep_type = USB_ENDPOINT_TYPE_CONTROL; + ep0_cfg.hport = hport; + /* Allocate memory for roothub port control endpoint */ + usbh_ep_alloc(&hport->ep0, &ep0_cfg); + + usb_osal_leave_critical_section(flags); +} + +void usbh_hport_deactivate(struct usbh_hubport *hport) +{ + uint32_t flags; + + flags = usb_osal_enter_critical_section(); + /* Don't free the control pipe of root hub ports! */ + if (hport->parent != NULL && hport->ep0 != NULL) { + usb_ep_cancel(hport->ep0); + usbh_ep_free(hport->ep0); + hport->ep0 = NULL; + } + /* Free the device address if one has been assigned */ + usbh_devaddr_destroy(hport, hport->dev_addr); + hport->dev_addr = 0; + + usb_osal_leave_critical_section(flags); +} + +void usbh_event_notify_handler(uint8_t event, uint8_t rhport) +{ + switch (event) { + case USBH_EVENT_ATTACHED: + if (!usbh_core_cfg.rhport[rhport - 1].hport.connected) { + usbh_core_cfg.rhport[rhport - 1].hport.connected = true; + usbh_core_cfg.rhport[rhport - 1].hport.port_change = true; + if (usbh_core_cfg.pscwait) { + usbh_core_cfg.pscwait = false; + usb_osal_sem_give(usbh_core_cfg.pscsem); + } + } + break; + case USBH_EVENT_REMOVED: + if (usbh_core_cfg.rhport[rhport - 1].hport.connected) { + usbh_core_cfg.rhport[rhport - 1].hport.connected = false; + usbh_core_cfg.rhport[rhport - 1].hport.port_change = true; + if (usbh_core_cfg.pscwait) { + usbh_core_cfg.pscwait = false; + usb_osal_sem_give(usbh_core_cfg.pscsem); + } + } + break; + default: + break; + } +} + +int usbh_initialize(void) +{ + usb_osal_thread_t usb_thread; + + memset(&usbh_core_cfg, 0, sizeof(struct usbh_core_priv)); + + usbh_workq_initialize(); + + usbh_core_cfg.pscsem = usb_osal_sem_create(0); + if (usbh_core_cfg.pscsem == NULL) { + return -1; + } + + usb_thread = usb_osal_thread_create("usbh_psc", CONFIG_USBHOST_PSC_STACKSIZE, CONFIG_USBHOST_PSC_PRIO, usbh_portchange_detect_thread, NULL); + if (usb_thread == NULL) { + return -1; + } + + return 0; +} + +int lsusb(int argc, char **argv) +{ + usb_slist_t *hub_list; + uint8_t port; + + if (argc < 2) { + printf("Usage: lsusb [options]...\r\n"); + printf("List USB devices\r\n"); + printf(" -v, --verbose\r\n"); + printf(" Increase verbosity (show descriptors)\r\n"); + printf(" -s [[bus]:[devnum]]\r\n"); + printf(" Show only devices with specified device and/or bus numbers (in decimal)\r\n"); + printf(" -d vendor:[product]\r\n"); + printf(" Show only devices with the specified vendor and product ID numbers (in hexadecimal)\r\n"); + printf(" -t, --tree\r\n"); + printf(" Dump the physical USB device hierachy as a tree\r\n"); + printf(" -V, --version\r\n"); + printf(" Show version of program\r\n"); + printf(" -h, --help\r\n"); + printf(" Show usage and help\r\n"); + return 0; + } + + if (argc > 3) { + return 0; + } + + if (strcmp(argv[1], "-t") == 0) { + for (port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { + if (usbh_core_cfg.rhport[port - 1].hport.connected) { + printf("/: Bus %02u,VID:PID 0x%04x:0x%04x\r\n", USBH_ROOT_HUB_INDEX, usbh_core_cfg.rhport[port - 1].hport.device_desc.idVendor, usbh_core_cfg.rhport[port - 1].hport.device_desc.idProduct); + + for (uint8_t i = 0; i < usbh_core_cfg.rhport[port - 1].hport.config.config_desc.bNumInterfaces; i++) { + if (usbh_core_cfg.rhport[port - 1].hport.config.intf[i].class_driver->driver_name) { + printf(" |__Port %u,Port addr:0x%02x,If %u,ClassDriver=%s\r\n", usbh_core_cfg.rhport[port - 1].hport.port, usbh_core_cfg.rhport[port - 1].hport.dev_addr, + i, usbh_core_cfg.rhport[port - 1].hport.config.intf[i].class_driver->driver_name); + } + } + } + } + usb_slist_for_each(hub_list, &hub_class_head) + { + usbh_hub_t *hub_class = usb_slist_entry(hub_list, struct usbh_hub, list); + + for (port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) { + if (hub_class->child[port - 1].connected) { + printf("/: Bus %02u,VID:PID 0x%04x:0x%04x\r\n", hub_class->index, hub_class->child[port - 1].device_desc.idVendor, hub_class->child[port - 1].device_desc.idProduct); + + for (uint8_t i = 0; i < hub_class->child[port - 1].config.config_desc.bNumInterfaces; i++) { + if (hub_class->child[port - 1].config.intf[i].class_driver->driver_name) { + printf(" |__Port %u,Port addr:0x%02x,If %u,ClassDriver=%s\r\n", hub_class->child[port - 1].port, hub_class->child[port - 1].dev_addr, + i, hub_class->child[port - 1].config.intf[i].class_driver->driver_name); + } + } + } + } + } + } else if (strcmp(argv[1], "-v") == 0) { + for (port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { + if (usbh_core_cfg.rhport[port - 1].hport.connected) { + printf("Bus %02u,Port %u,Port addr:0x%02x,VID:PID 0x%04x:0x%04x\r\n", USBH_ROOT_HUB_INDEX, usbh_core_cfg.rhport[port - 1].hport.port, usbh_core_cfg.rhport[port - 1].hport.dev_addr, + usbh_core_cfg.rhport[port - 1].hport.device_desc.idVendor, usbh_core_cfg.rhport[port - 1].hport.device_desc.idProduct); + usbh_print_hubport_info(&usbh_core_cfg.rhport[port - 1].hport); + } + } + + usb_slist_for_each(hub_list, &hub_class_head) + { + usbh_hub_t *hub_class = usb_slist_entry(hub_list, struct usbh_hub, list); + + for (port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) { + if (hub_class->child[port - 1].connected) { + printf("Bus %02u,Port %u,Port addr:0x%02x,VID:PID 0x%04x:0x%04x\r\n", hub_class->index, hub_class->child[port - 1].port, hub_class->child[port - 1].dev_addr, + hub_class->child[port - 1].device_desc.idVendor, hub_class->child[port - 1].device_desc.idProduct); + usbh_print_hubport_info(&hub_class->child[port - 1]); + } + } + } + } + + return 0; +} + +struct usbh_hubport *usbh_get_hubport(uint8_t dev_addr) +{ + usb_slist_t *hub_list; + uint8_t port; + + for (port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { + if (usbh_core_cfg.rhport[port - 1].hport.connected) { + if (usbh_core_cfg.rhport[port - 1].hport.dev_addr == dev_addr) { + return &usbh_core_cfg.rhport[port - 1].hport; + } + } + } + usb_slist_for_each(hub_list, &hub_class_head) + { + usbh_hub_t *hub_class = usb_slist_entry(hub_list, struct usbh_hub, list); + + for (port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) { + if (hub_class->child[port - 1].connected) { + if (hub_class->child[port - 1].dev_addr == dev_addr) { + return &hub_class->child[port - 1]; + } + } + } + } + return NULL; +} + +void *usbh_get_class(uint8_t dev_addr, uint8_t intf) +{ + usb_slist_t *hub_list; + uint8_t port; + + for (port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { + if (usbh_core_cfg.rhport[port - 1].hport.connected) { + if (usbh_core_cfg.rhport[port - 1].hport.dev_addr == dev_addr) { + if (usbh_core_cfg.rhport[port - 1].hport.config.intf[intf].priv) { + return usbh_core_cfg.rhport[port - 1].hport.config.intf[intf].priv; + } + } + } + } + usb_slist_for_each(hub_list, &hub_class_head) + { + usbh_hub_t *hub_class = usb_slist_entry(hub_list, struct usbh_hub, list); + + for (port = USBH_HUB_PORT_START_INDEX; port <= hub_class->nports; port++) { + if (hub_class->child[port - 1].connected) { + if (hub_class->child[port - 1].dev_addr == dev_addr) { + if (hub_class->child[port - 1].config.intf[intf].priv) { + return hub_class->child[port - 1].config.intf[intf].priv; + } + } + } + } + } + return NULL; +} + +const struct usbh_class_info class_info_table[] = { + + { .class = USB_DEVICE_CLASS_CDC, + .subclass = CDC_ABSTRACT_CONTROL_MODEL, + .protocol = CDC_COMMON_PROTOCOL_AT_COMMANDS, + .vid = 0x00, + .pid = 0x00, + .class_driver = &cdc_acm_class_driver }, + { .class = USB_DEVICE_CLASS_HID, + .subclass = HID_SUBCLASS_BOOTIF, + .protocol = HID_PROTOCOL_KEYBOARD, + .vid = 0x00, + .pid = 0x00, + .class_driver = &hid_class_driver }, + { .class = USB_DEVICE_CLASS_HID, + .subclass = HID_SUBCLASS_BOOTIF, + .protocol = HID_PROTOCOL_MOUSE, + .vid = 0x00, + .pid = 0x00, + .class_driver = &hid_class_driver }, + { .class = USB_DEVICE_CLASS_MASS_STORAGE, + .subclass = MSC_SUBCLASS_SCSI, + .protocol = MSC_PROTOCOL_BULK_ONLY, + .vid = 0x00, + .pid = 0x00, + .class_driver = &msc_class_driver }, +#ifdef CONFIG_USBHOST_HUB + { .class = USB_DEVICE_CLASS_HUB, + .subclass = 0, + .protocol = 0, + .vid = 0x00, + .pid = 0x00, + .class_driver = &hub_class_driver }, + { .class = USB_DEVICE_CLASS_HUB, + .subclass = 0, + .protocol = 1, + .vid = 0x00, + .pid = 0x00, + .class_driver = &hub_class_driver }, +#endif +}; + +static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subcalss, uint8_t protocol, uint16_t vid, uint16_t pid) +{ + for (uint8_t i = 0; i < sizeof(class_info_table) / sizeof(class_info_table[0]); i++) { + if (class == class_info_table[i].class && + subcalss == class_info_table[i].subclass && + protocol == class_info_table[i].protocol) { + /* If this is a vendor-specific class ID, then the VID and PID have to match as well. */ + if (class == USB_DEVICE_CLASS_VEND_SPECIFIC) { + if (vid == class_info_table[i].vid && + pid == class_info_table[i].pid) { + return class_info_table[i].class_driver; + } + } + return class_info_table[i].class_driver; + } + } + + return NULL; +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbh_core.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbh_core.h new file mode 100644 index 00000000..740c5380 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/core/usbh_core.h @@ -0,0 +1,128 @@ +/** + * @file usbh_core.h + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef _USBH_CORE_H +#define _USBH_CORE_H + +#include "usb_util.h" +#include "usb_def.h" +#include "usb_hc.h" +#include "usb_osal.h" +#include "usb_workq.h" +#include "usbh_hub.h" +#include "usb_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define USBH_ROOT_HUB_INDEX 1 /* roothub index*/ +#define USBH_EX_HUB_INDEX 2 /* external hub index */ +#define USBH_HUB_PORT_START_INDEX 1 /* first hub port index */ + +#ifdef CONFIG_USBHOST_HUB +#define ROOTHUB(hport) ((hport)->parent == NULL) +#else +#define ROOTHUB(hport) true +#endif + +#define CLASS_CONNECT(hport,i) ((hport)->config.intf[i].class_driver->connect(hport, i)) +#define CLASS_DISCONNECT(hport,i) ((hport)->config.intf[i].class_driver->disconnect(hport, i)) + +enum usbh_event_type { + USBH_EVENT_ATTACHED, + USBH_EVENT_REMOVED, +}; + +struct usbh_class_info { + uint8_t class; /* Base device class code */ + uint8_t subclass; /* Sub-class, depends on base class. Eg. */ + uint8_t protocol; /* Protocol, depends on base class. Eg. */ + uint16_t vid; /* Vendor ID (for vendor/product specific devices) */ + uint16_t pid; /* Product ID (for vendor/product specific devices) */ + const struct usbh_class_driver *class_driver; +}; + +struct usbh_hubport; +struct usbh_class_driver { + const char *driver_name; + int (*connect)(struct usbh_hubport *hport, uint8_t intf); + int (*disconnect)(struct usbh_hubport *hport, uint8_t intf); +}; + +typedef struct usbh_endpoint { + struct usb_endpoint_descriptor ep_desc; +} usbh_endpoint_t; + +typedef struct usbh_interface { + struct usb_interface_descriptor intf_desc; + struct usbh_endpoint ep[CONFIG_USBHOST_EP_NUM]; + struct usbh_class_driver *class_driver; + void *priv; +} usbh_interface_t; + +typedef struct usbh_configuration { + struct usb_configuration_descriptor config_desc; + struct usbh_interface intf[CONFIG_USBHOST_INTF_NUM]; +} usbh_configuration_t; + +typedef struct usbh_hubport { + bool connected; /* True: device connected; false: disconnected */ + bool port_change; /* True: port changed; false: port do not change */ + uint8_t port; /* Hub port index */ + uint8_t dev_addr; /* device address */ + uint8_t speed; /* device speed */ + usbh_epinfo_t ep0; /* control ep info */ + struct usb_device_descriptor device_desc; + struct usbh_configuration config; +#if 0 + uint8_t* config_desc; +#endif + struct usbh_hub *parent; /*if NULL, is roothub*/ +} usbh_hubport_t; + +typedef struct usbh_hub { + usb_slist_t list; + uint8_t index; /* Hub index */ + uint8_t nports; /* Hub port number */ + uint8_t dev_addr; /* Hub device address */ + usbh_epinfo_t intin; + uint8_t *int_buffer; + struct usb_setup_packet *setup; + struct hub_port_status *port_status; + struct usb_hub_descriptor hub_desc; + struct usbh_hubport child[CONFIG_USBHOST_EHPORTS]; + struct usbh_hubport *parent; /* Parent hub port */ + struct usb_work work; +} usbh_hub_t; + +void usbh_event_notify_handler(uint8_t event, uint8_t rhport); + +int usbh_initialize(void); +int lsusb(int argc, char **argv); +struct usbh_hubport *usbh_get_hubport(uint8_t dev_addr); +void *usbh_get_class(uint8_t dev_addr, uint8_t intf); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/usb_ch32_usbfs_reg.h b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/usb_ch32_usbfs_reg.h new file mode 100644 index 00000000..ca8e487a --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/usb_ch32_usbfs_reg.h @@ -0,0 +1,339 @@ +#ifndef _USB_CH32_USBFS_REG_H +#define _USB_CH32_USBFS_REG_H + +#define __IO volatile /* defines 'read / write' permissions */ + +/* USBOTG_FS Registers */ +typedef struct +{ + __IO uint8_t BASE_CTRL; + __IO uint8_t UDEV_CTRL; + __IO uint8_t INT_EN; + __IO uint8_t DEV_ADDR; + __IO uint8_t Reserve0; + __IO uint8_t MIS_ST; + __IO uint8_t INT_FG; + __IO uint8_t INT_ST; + __IO uint16_t RX_LEN; + __IO uint16_t Reserve1; + __IO uint8_t UEP4_1_MOD; + __IO uint8_t UEP2_3_MOD; + __IO uint8_t UEP5_6_MOD; + __IO uint8_t UEP7_MOD; + __IO uint32_t UEP0_DMA; + __IO uint32_t UEP1_DMA; + __IO uint32_t UEP2_DMA; + __IO uint32_t UEP3_DMA; + __IO uint32_t UEP4_DMA; + __IO uint32_t UEP5_DMA; + __IO uint32_t UEP6_DMA; + __IO uint32_t UEP7_DMA; + __IO uint16_t UEP0_TX_LEN; + __IO uint8_t UEP0_TX_CTRL; + __IO uint8_t UEP0_RX_CTRL; + __IO uint16_t UEP1_TX_LEN; + __IO uint8_t UEP1_TX_CTRL; + __IO uint8_t UEP1_RX_CTRL; + __IO uint16_t UEP2_TX_LEN; + __IO uint8_t UEP2_TX_CTRL; + __IO uint8_t UEP2_RX_CTRL; + __IO uint16_t UEP3_TX_LEN; + __IO uint8_t UEP3_TX_CTRL; + __IO uint8_t UEP3_RX_CTRL; + __IO uint16_t UEP4_TX_LEN; + __IO uint8_t UEP4_TX_CTRL; + __IO uint8_t UEP4_RX_CTRL; + __IO uint16_t UEP5_TX_LEN; + __IO uint8_t UEP5_TX_CTRL; + __IO uint8_t UEP5_RX_CTRL; + __IO uint16_t UEP6_TX_LEN; + __IO uint8_t UEP6_TX_CTRL; + __IO uint8_t UEP6_RX_CTRL; + __IO uint16_t UEP7_TX_LEN; + __IO uint8_t UEP7_TX_CTRL; + __IO uint8_t UEP7_RX_CTRL; + __IO uint32_t Reserve2; + __IO uint32_t OTG_CR; + __IO uint32_t OTG_SR; +} USBOTG_FS_TypeDef; + +typedef struct __attribute__((packed)) { + __IO uint8_t BASE_CTRL; + __IO uint8_t HOST_CTRL; + __IO uint8_t INT_EN; + __IO uint8_t DEV_ADDR; + __IO uint8_t Reserve0; + __IO uint8_t MIS_ST; + __IO uint8_t INT_FG; + __IO uint8_t INT_ST; + __IO uint16_t RX_LEN; + __IO uint16_t Reserve1; + __IO uint8_t Reserve2; + __IO uint8_t HOST_EP_MOD; + __IO uint16_t Reserve3; + __IO uint32_t Reserve4; + __IO uint32_t Reserve5; + __IO uint32_t HOST_RX_DMA; + __IO uint32_t HOST_TX_DMA; + __IO uint32_t Reserve6; + __IO uint32_t Reserve7; + __IO uint32_t Reserve8; + __IO uint32_t Reserve9; + __IO uint32_t Reserve10; + __IO uint16_t Reserve11; + __IO uint16_t HOST_SETUP; + __IO uint8_t HOST_EP_PID; + __IO uint8_t Reserve12; + __IO uint8_t Reserve13; + __IO uint8_t HOST_RX_CTRL; + __IO uint16_t HOST_TX_LEN; + __IO uint8_t HOST_TX_CTRL; + __IO uint8_t Reserve14; + __IO uint32_t Reserve15; + __IO uint32_t Reserve16; + __IO uint32_t Reserve17; + __IO uint32_t Reserve18; + __IO uint32_t Reserve19; + __IO uint32_t OTG_CR; + __IO uint32_t OTG_SR; +} USBOTGH_FS_TypeDef; + +#define USBFS_BASE ((uint32_t)0x50000000) + +#define USBFS_DEVICE ((USBOTG_FS_TypeDef *)USBFS_BASE) +#define USBFS_HOST ((USBOTGH_FS_TypeDef *)USBFS_BASE) + +/******************* GLOBAL ******************/ + +/* BASE USB_CTRL */ +#define USBFS_BASE_CTRL_OFFSET 0x00 // USB base control +#define USBFS_UC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode +#define USBFS_UC_LOW_SPEED 0x40 // enable USB low speed: 0=12Mbps, 1=1.5Mbps +#define USBFS_UC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable +#define USBFS_UC_SYS_CTRL1 0x20 // USB system control high bit +#define USBFS_UC_SYS_CTRL0 0x10 // USB system control low bit +#define USBFS_UC_SYS_CTRL_MASK 0x30 // bit mask of USB system control +// UC_HOST_MODE & UC_SYS_CTRL1 & UC_SYS_CTRL0: USB system control +// 0 00: disable USB device and disable internal pullup resistance +// 0 01: enable USB device and disable internal pullup resistance, need external pullup resistance +// 0 1x: enable USB device and enable internal pullup resistance +// 1 00: enable USB host and normal status +// 1 01: enable USB host and force UDP/UDM output SE0 state +// 1 10: enable USB host and force UDP/UDM output J state +// 1 11: enable USB host and force UDP/UDM output resume or K state +#define USBFS_UC_INT_BUSY 0x08 // enable automatic responding busy for device mode or automatic pause for host mode during interrupt flag UIF_TRANSFER valid +#define USBFS_UC_RESET_SIE 0x04 // force reset USB SIE, need software clear +#define USBFS_UC_CLR_ALL 0x02 // force clear FIFO and count of USB +#define USBFS_UC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB + +/* USB INT EN */ +#define USBFS_INT_EN_OFFSET 0x02 +#define USBFS_UIE_DEV_SOF 0x80 // enable interrupt for SOF received for USB device mode +#define USBFS_UIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode +#define USBFS_UIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow +#define USBFS_UIE_HST_SOF 0x08 // enable interrupt for host SOF timer action for USB host mode +#define USBFS_UIE_SUSPEND 0x04 // enable interrupt for USB suspend or resume event +#define USBFS_UIE_TRANSFER 0x02 // enable interrupt for USB transfer completion +#define USBFS_UIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode +#define USBFS_UIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode +/* USB_DEV_ADDR */ +#define USBFS_DEV_ADDR_OFFSET 0x03 +#define USBFS_UDA_GP_BIT 0x80 // general purpose bit +#define USBFS_USB_ADDR_MASK 0x7F // bit mask for USB device address + +/* USB_STATUS */ +#define USBFS_USB_STATUS_OFFSET 0x04 + +/* USB_MIS_ST */ +#define USBFS_MIS_ST_OFFSET 0x05 +#define USBFS_UMS_SOF_PRES 0x80 // RO, indicate host SOF timer presage status +#define USBFS_UMS_SOF_ACT 0x40 // RO, indicate host SOF timer action status for USB host +#define USBFS_UMS_SIE_FREE 0x20 // RO, indicate USB SIE free status +#define USBFS_UMS_R_FIFO_RDY 0x10 // RO, indicate USB receiving FIFO ready status (not empty) +#define USBFS_UMS_BUS_RESET 0x08 // RO, indicate USB bus reset status +#define USBFS_UMS_SUSPEND 0x04 // RO, indicate USB suspend status +#define USBFS_UMS_DM_LEVEL 0x02 // RO, indicate UDM level saved at device attached to USB host +#define USBFS_UMS_DEV_ATTACH 0x01 // RO, indicate device attached status on USB host + +/* USB_INT_FG */ +#define USBFS_INT_FG_OFFSET 0x06 +#define USBFS_U_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received +#define USBFS_U_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK +#define USBFS_U_SIE_FREE 0x20 // RO, indicate USB SIE free status +#define USBFS_UIF_FIFO_OV 0x10 // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear +#define USBFS_UIF_HST_SOF 0x08 // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear +#define USBFS_UIF_SUSPEND 0x04 // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear +#define USBFS_UIF_TRANSFER 0x02 // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear +#define USBFS_UIF_DETECT 0x01 // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear +#define USBFS_UIF_BUS_RST 0x01 // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear + +/* USB_INT_ST */ +#define USBFS_INT_ST_OFFSET 0x07 +#define USBFS_UIS_IS_SETUP 0x80 // RO, indicate current USB transfer is setup received for USB device mode +#define USBFS_UIS_IS_NAK 0x80 // RO, indicate current USB transfer is NAK received for USB device mode +#define USBFS_UIS_TOG_OK 0x40 // RO, indicate current USB transfer toggle is OK +#define USBFS_UIS_TOKEN1 0x20 // RO, current token PID code bit 1 received for USB device mode +#define USBFS_UIS_TOKEN0 0x10 // RO, current token PID code bit 0 received for USB device mode +#define USBFS_UIS_TOKEN_MASK 0x30 // RO, bit mask of current token PID code received for USB device mode +#define USBFS_UIS_TOKEN_OUT 0x00 +#define USBFS_UIS_TOKEN_SOF 0x10 +#define USBFS_UIS_TOKEN_IN 0x20 +#define USBFS_UIS_TOKEN_SETUP 0x30 +// UIS_TOKEN1 & UIS_TOKEN0: current token PID code received for USB device mode +// 00: OUT token PID received +// 01: SOF token PID received +// 10: IN token PID received +// 11: SETUP token PID received +#define USBFS_UIS_ENDP_MASK 0x0F // RO, bit mask of current transfer endpoint number for USB device mode +/* USB_RX_LEN */ +#define USBFS_RX_LEN_OFFSET 0x08 + +/******************* DEVICE ******************/ + +/* UDEV_CTRL */ +#define USBFS_UDEV_CTRL_OFFSET 0x01 +#define USBFS_UD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable +#define USBFS_UD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level +#define USBFS_UD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level +#define USBFS_UD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed +#define USBFS_UD_GP_BIT 0x02 // general purpose bit +#define USBFS_UD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable + +/* UEP4_1_MOD */ +#define USBFS_UEP4_1_MOD_OFFSET 0x0C +#define USBFS_UEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT) +#define USBFS_UEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN) +#define USBFS_UEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1 +// UEPn_RX_EN & UEPn_TX_EN & UEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA +// 0 0 x: disable endpoint and disable buffer +// 1 0 0: 64 bytes buffer for receiving (OUT endpoint) +// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes +// 0 1 0: 64 bytes buffer for transmittal (IN endpoint) +// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes +// 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes +// 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes +#define USBFS_UEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT) +#define USBFS_UEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN) +// UEP4_RX_EN & UEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA +// 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) +// 1 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receiving (OUT endpoint), total=128bytes +// 0 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=128bytes +// 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) +// + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes + +/* UEP2_3_MOD */ +#define USBFS_UEP2_3_MOD_OFFSET 0x0D +#define USBFS_UEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT) +#define USBFS_UEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN) +#define USBFS_UEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3 +#define USBFS_UEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT) +#define USBFS_UEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN) +#define USBFS_UEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2 + +/* UEP5_6_MOD */ +#define USBFS_UEP5_6_MOD_OFFSET 0x0E +#define USBFS_UEP6_RX_EN 0x80 // enable USB endpoint 6 receiving (OUT) +#define USBFS_UEP6_TX_EN 0x40 // enable USB endpoint 6 transmittal (IN) +#define USBFS_UEP6_BUF_MOD 0x10 // buffer mode of USB endpoint 6 +#define USBFS_UEP5_RX_EN 0x08 // enable USB endpoint 5 receiving (OUT) +#define USBFS_UEP5_TX_EN 0x04 // enable USB endpoint 5 transmittal (IN) +#define USBFS_UEP5_BUF_MOD 0x01 // buffer mode of USB endpoint 5 + +/* UEP7_MOD */ +#define USBFS_UEP7_MOD_OFFSET 0x0F +#define USBFS_UEP7_RX_EN 0x08 // enable USB endpoint 7 receiving (OUT) +#define USBFS_UEP7_TX_EN 0x04 // enable USB endpoint 7 transmittal (IN) +#define USBFS_UEP7_BUF_MOD 0x01 // buffer mode of USB endpoint 7 + +/* USB_DMA */ +#define USBFS_UEPx_DMA_OFFSET(n) (0x10 + 4 * (n)) // endpoint x DMA buffer address +#define USBFS_UEP0_DMA_OFFSET 0x10 // endpoint 0 DMA buffer address +#define USBFS_UEP1_DMA_OFFSET 0x14 // endpoint 1 DMA buffer address +#define USBFS_UEP2_DMA_OFFSET 0x18 // endpoint 2 DMA buffer address +#define USBFS_UEP3_DMA_OFFSET 0x1c // endpoint 3 DMA buffer address +#define USBFS_UEP4_DMA_OFFSET 0x20 // endpoint 4 DMA buffer address +#define USBFS_UEP5_DMA_OFFSET 0x24 // endpoint 5 DMA buffer address +#define USBFS_UEP6_DMA_OFFSET 0x28 // endpoint 6 DMA buffer address +#define USBFS_UEP7_DMA_OFFSET 0x2c // endpoint 7 DMA buffer address +/* USB_EP_CTRL */ +#define USBFS_UEPx_T_LEN_OFFSET(n) (0x30 + 4 * (n)) // endpoint x DMA buffer address +#define USBFS_UEPx_TX_CTRL_OFFSET(n) (0x30 + 4 * (n) + 2) // endpoint x DMA buffer address +#define USBFS_UEPx_RX_CTRL_OFFSET(n) (0x30 + 4 * (n) + 3) // endpoint x DMA buffer address + +#define USBFS_UEP_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle +#define USBFS_UEP_R_TOG 0x04 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1 +#define USBFS_UEP_T_TOG 0x04 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 + +#define USBFS_UEP_R_RES1 0x02 // handshake response type high bit for USB endpoint X receiving (OUT) +#define USBFS_UEP_R_RES0 0x01 // handshake response type low bit for USB endpoint X receiving (OUT) +#define USBFS_UEP_R_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X receiving (OUT) +#define USBFS_UEP_R_RES_ACK 0x00 +#define USBFS_UEP_R_RES_TOUT 0x01 +#define USBFS_UEP_R_RES_NAK 0x02 +#define USBFS_UEP_R_RES_STALL 0x03 +// RB_UEP_R_RES1 & RB_UEP_R_RES0: handshake response type for USB endpoint X receiving (OUT) +// 00: ACK (ready) +// 01: no response, time out to host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) +#define USBFS_UEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN) +#define USBFS_UEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN) +#define USBFS_UEP_T_RES_MASK 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN) +#define USBFS_UEP_T_RES_ACK 0x00 +#define USBFS_UEP_T_RES_TOUT 0x01 +#define USBFS_UEP_T_RES_NAK 0x02 +#define USBFS_UEP_T_RES_STALL 0x03 +// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN) +// 00: DATA0 or DATA1 then expecting ACK (ready) +// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: TALL (error) + +/******************* HOST ******************/ + +#define USBFS_UHOST_CTRL_OFFSET 0x01 // USB host physical prot control +#define USBFS_UH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable +#define USBFS_UH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level +#define USBFS_UH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level +#define USBFS_UH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed +#define USBFS_UH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset +#define USBFS_UH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached + +#define USBFS_UH_EP_MOD_OFFSET USBFS_UEP2_3_MOD_OFFSET +#define USBFS_UH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal +#define USBFS_UH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint +// bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA +// 0 x: disable endpoint and disable buffer +// 1 0: 64 bytes buffer for transmittal (OUT endpoint) +// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes +#define USBFS_UH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving +#define USBFS_UH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint +// bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA +// 0 x: disable endpoint and disable buffer +// 1 0: 64 bytes buffer for receiving (IN endpoint) +// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes + +#define USBFS_UH_RX_DMA_OFFSET USBFS_UEPx_DMA_OFFSET(2) // host rx endpoint buffer high address +#define USBFS_UH_TX_DMA_OFFSET USBFS_UEPx_DMA_OFFSET(3) // host tx endpoint buffer high address + +#define USBFS_UH_SETUP_OFFSET USBFS_UEPx_TX_CTRL_OFFSET(1) +#define USBFS_UH_PRE_PID_EN 0x0400 // USB host PRE PID enable for low speed device via hub +#define USBFS_UH_SOF_EN 0x04 // USB host automatic SOF enable + +#define USBFS_UH_EP_PID_OFFSET USBFS_UEPx_T_LEN_OFFSET(2) +#define USBFS_UH_TOKEN_MASK 0xF0 // bit mask of token PID for USB host transfer +#define USBFS_UH_ENDP_MASK 0x0F // bit mask of endpoint number for USB host transfer + +#define USBFS_UH_RX_CTRL_OFFSET USBFS_UEPx_RX_CTRL_OFFSET(2) // host receiver endpoint control +#define USBFS_UH_R_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle +#define USBFS_UH_R_TOG 0x04 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1 +#define USBFS_UH_R_RES 0x01 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions + +#define USBFS_UH_TX_LEN_OFFSET USBFS_UEPx_T_LEN_OFFSET(3) + +#define USBFS_UH_TX_CTRL_OFFSET USBFS_UEPx_TX_CTRL_OFFSET(3) // host transmittal endpoint control +#define USBFS_UH_T_AUTO_TOG 0x08 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle +#define USBFS_UH_T_TOG 0x04 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1 +#define USBFS_UH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions + +#endif diff --git a/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/usb_dc_usbfs.c b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/usb_dc_usbfs.c new file mode 100644 index 00000000..b8019570 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/CherryUSB/usb_dc_usbfs.c @@ -0,0 +1,630 @@ +#include "usbd_core.h" +#include "usb_ch32_usbfs_reg.h" + +#ifndef USB_NUM_BIDIR_ENDPOINTS +#define USB_NUM_BIDIR_ENDPOINTS 8 +#endif + +/* Endpoint state */ +struct usb_dc_ep_state { + /** Endpoint max packet size */ + uint16_t ep_mps; + /** Endpoint Transfer Type. + * May be Bulk, Interrupt, Control or Isochronous + */ + uint8_t ep_type; + uint8_t ep_stalled; /** Endpoint stall flag */ +}; + +/* Driver state */ +struct usb_dc_config_priv { + volatile uint8_t dev_addr; + struct usb_dc_ep_state in_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< IN endpoint parameters*/ + struct usb_dc_ep_state out_ep[USB_NUM_BIDIR_ENDPOINTS]; /*!< OUT endpoint parameters */ +} usb_dc_cfg; + +/* Endpoint Buffer */ +__attribute__((aligned(4))) uint8_t EP0_DatabufHD[64]; //ep0(64) +__attribute__((aligned(4))) uint8_t EP1_DatabufHD[64 + 64]; //ep1_out(64)+ep1_in(64) +__attribute__((aligned(4))) uint8_t EP2_DatabufHD[64 + 64]; //ep2_out(64)+ep2_in(64) +__attribute__((aligned(4))) uint8_t EP3_DatabufHD[64 + 64]; //ep3_out(64)+ep3_in(64) +__attribute__((aligned(4))) uint8_t EP4_DatabufHD[64 + 64]; //ep4_out(64)+ep4_in(64) +__attribute__((aligned(4))) uint8_t EP5_DatabufHD[64 + 64]; //ep5_out(64)+ep5_in(64) +__attribute__((aligned(4))) uint8_t EP6_DatabufHD[64 + 64]; //ep6_out(64)+ep6_in(64) +__attribute__((aligned(4))) uint8_t EP7_DatabufHD[64 + 64]; //ep7_out(64)+ep7_in(64) + +void OTG_FS_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); + +volatile uint8_t mps_over_flag = 0; + +__WEAK void usb_dc_low_level_init(void) +{ +} + +__WEAK void usb_dc_low_level_deinit(void) +{ +} + +int usb_dc_init(void) +{ + memset(&usb_dc_cfg, 0, sizeof(struct usb_dc_config_priv)); + + usb_dc_low_level_init(); + + USBFS_DEVICE->BASE_CTRL = 0x00; + + USBFS_DEVICE->UEP4_1_MOD = USBFS_UEP4_RX_EN | USBFS_UEP4_TX_EN | USBFS_UEP1_RX_EN | USBFS_UEP1_TX_EN; + USBFS_DEVICE->UEP2_3_MOD = USBFS_UEP2_RX_EN | USBFS_UEP2_TX_EN | USBFS_UEP3_RX_EN | USBFS_UEP3_TX_EN; + USBFS_DEVICE->UEP5_6_MOD = USBFS_UEP5_RX_EN | USBFS_UEP5_TX_EN | USBFS_UEP6_RX_EN | USBFS_UEP6_TX_EN; + USBFS_DEVICE->UEP7_MOD = USBFS_UEP7_RX_EN | USBFS_UEP7_TX_EN; + + USBFS_DEVICE->UEP0_DMA = (uint32_t)EP0_DatabufHD; + USBFS_DEVICE->UEP1_DMA = (uint32_t)EP1_DatabufHD; + USBFS_DEVICE->UEP2_DMA = (uint32_t)EP2_DatabufHD; + USBFS_DEVICE->UEP3_DMA = (uint32_t)EP3_DatabufHD; + USBFS_DEVICE->UEP4_DMA = (uint32_t)EP4_DatabufHD; + USBFS_DEVICE->UEP5_DMA = (uint32_t)EP5_DatabufHD; + USBFS_DEVICE->UEP6_DMA = (uint32_t)EP6_DatabufHD; + USBFS_DEVICE->UEP7_DMA = (uint32_t)EP7_DatabufHD; + + USBFS_DEVICE->UEP0_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP1_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP2_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP3_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP4_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP5_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP6_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP7_RX_CTRL = USBFS_UEP_R_RES_ACK; + + USBFS_DEVICE->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP1_TX_LEN = 0; + USBFS_DEVICE->UEP2_TX_LEN = 0; + USBFS_DEVICE->UEP3_TX_LEN = 0; + USBFS_DEVICE->UEP4_TX_LEN = 0; + USBFS_DEVICE->UEP5_TX_LEN = 0; + USBFS_DEVICE->UEP6_TX_LEN = 0; + USBFS_DEVICE->UEP7_TX_LEN = 0; + + USBFS_DEVICE->UEP1_TX_CTRL = USBFS_UEP_T_RES_NAK | USBFS_UEP_AUTO_TOG; + USBFS_DEVICE->UEP2_TX_CTRL = USBFS_UEP_T_RES_NAK | USBFS_UEP_AUTO_TOG; + USBFS_DEVICE->UEP3_TX_CTRL = USBFS_UEP_T_RES_NAK | USBFS_UEP_AUTO_TOG; + USBFS_DEVICE->UEP4_TX_CTRL = USBFS_UEP_T_RES_NAK | USBFS_UEP_AUTO_TOG; + USBFS_DEVICE->UEP5_TX_CTRL = USBFS_UEP_T_RES_NAK | USBFS_UEP_AUTO_TOG; + USBFS_DEVICE->UEP6_TX_CTRL = USBFS_UEP_T_RES_NAK | USBFS_UEP_AUTO_TOG; + USBFS_DEVICE->UEP7_TX_CTRL = USBFS_UEP_T_RES_NAK | USBFS_UEP_AUTO_TOG; + + USBFS_DEVICE->INT_FG = 0xFF; + USBFS_DEVICE->INT_EN = USBFS_UIE_SUSPEND | USBFS_UIE_BUS_RST | USBFS_UIE_TRANSFER; + USBFS_DEVICE->DEV_ADDR = 0x00; + + USBFS_DEVICE->BASE_CTRL = USBFS_UC_DEV_PU_EN | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN; + USBFS_DEVICE->UDEV_CTRL = USBFS_UD_PD_DIS | USBFS_UD_PORT_EN; + return 0; +} + +void usb_dc_deinit(void) +{ +} + +int usbd_set_address(const uint8_t addr) +{ + if (addr == 0) { + USBFS_DEVICE->DEV_ADDR = (USBFS_DEVICE->DEV_ADDR & USBFS_UDA_GP_BIT) | 0; + } + usb_dc_cfg.dev_addr = addr; + return 0; +} + +int usbd_ep_open(const struct usbd_endpoint_cfg *ep_cfg) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep_cfg->ep_addr); + + if (USB_EP_DIR_IS_OUT(ep_cfg->ep_addr)) { + usb_dc_cfg.out_ep[ep_idx].ep_mps = ep_cfg->ep_mps; + usb_dc_cfg.out_ep[ep_idx].ep_type = ep_cfg->ep_type; + } else { + usb_dc_cfg.in_ep[ep_idx].ep_mps = ep_cfg->ep_mps; + usb_dc_cfg.in_ep[ep_idx].ep_type = ep_cfg->ep_type; + } + return 0; +} +int usbd_ep_close(const uint8_t ep) +{ + return 0; +} +int usbd_ep_set_stall(const uint8_t ep) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (USB_EP_DIR_IS_OUT(ep)) { + switch (ep_idx) { + case 0: + USBFS_DEVICE->UEP0_RX_CTRL = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_STALL; + break; + case 1: + USBFS_DEVICE->UEP1_RX_CTRL = (USBFS_DEVICE->UEP1_RX_CTRL &= ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_STALL; + break; + case 2: + USBFS_DEVICE->UEP2_RX_CTRL = (USBFS_DEVICE->UEP2_RX_CTRL &= ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_STALL; + break; + case 3: + USBFS_DEVICE->UEP3_RX_CTRL = (USBFS_DEVICE->UEP3_RX_CTRL &= ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_STALL; + break; + case 4: + USBFS_DEVICE->UEP4_RX_CTRL = (USBFS_DEVICE->UEP4_RX_CTRL &= ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_STALL; + break; + case 5: + USBFS_DEVICE->UEP5_RX_CTRL = (USBFS_DEVICE->UEP5_RX_CTRL &= ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_STALL; + break; + case 6: + USBFS_DEVICE->UEP6_RX_CTRL = (USBFS_DEVICE->UEP6_RX_CTRL &= ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_STALL; + break; + case 7: + USBFS_DEVICE->UEP7_RX_CTRL = (USBFS_DEVICE->UEP7_RX_CTRL &= ~USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_STALL; + break; + default: + break; + } + + } else { + switch (ep_idx) { + case 0: + USBFS_DEVICE->UEP0_TX_CTRL = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_STALL; + break; + case 1: + USBFS_DEVICE->UEP1_TX_CTRL = (USBFS_DEVICE->UEP1_TX_CTRL &= ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_STALL; + break; + case 2: + USBFS_DEVICE->UEP2_TX_CTRL = (USBFS_DEVICE->UEP2_TX_CTRL &= ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_STALL; + break; + case 3: + USBFS_DEVICE->UEP3_TX_CTRL = (USBFS_DEVICE->UEP3_TX_CTRL &= ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_STALL; + break; + case 4: + USBFS_DEVICE->UEP4_TX_CTRL = (USBFS_DEVICE->UEP4_TX_CTRL &= ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_STALL; + break; + case 5: + USBFS_DEVICE->UEP5_TX_CTRL = (USBFS_DEVICE->UEP5_TX_CTRL &= ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_STALL; + break; + case 6: + USBFS_DEVICE->UEP6_TX_CTRL = (USBFS_DEVICE->UEP6_TX_CTRL &= ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_STALL; + break; + case 7: + USBFS_DEVICE->UEP7_TX_CTRL = (USBFS_DEVICE->UEP7_TX_CTRL &= ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_STALL; + break; + default: + break; + } + } + + return 0; +} + +int usbd_ep_clear_stall(const uint8_t ep) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (USB_EP_DIR_IS_OUT(ep)) { + switch (ep_idx) { + case 0: + + break; + case 1: + USBFS_DEVICE->UEP1_RX_CTRL = (USBFS_DEVICE->UEP1_RX_CTRL & ~(USBFS_UEP_R_TOG | USBFS_UEP_R_RES_MASK)) | USBFS_UEP_R_RES_ACK; + break; + case 2: + USBFS_DEVICE->UEP2_RX_CTRL = (USBFS_DEVICE->UEP2_RX_CTRL & ~(USBFS_UEP_R_TOG | USBFS_UEP_R_RES_MASK)) | USBFS_UEP_R_RES_ACK; + break; + case 3: + USBFS_DEVICE->UEP3_RX_CTRL = (USBFS_DEVICE->UEP3_RX_CTRL & ~(USBFS_UEP_R_TOG | USBFS_UEP_R_RES_MASK)) | USBFS_UEP_R_RES_ACK; + break; + case 4: + USBFS_DEVICE->UEP4_RX_CTRL = (USBFS_DEVICE->UEP4_RX_CTRL & ~(USBFS_UEP_R_TOG | USBFS_UEP_R_RES_MASK)) | USBFS_UEP_R_RES_ACK; + break; + case 5: + USBFS_DEVICE->UEP5_RX_CTRL = (USBFS_DEVICE->UEP5_RX_CTRL & ~(USBFS_UEP_R_TOG | USBFS_UEP_R_RES_MASK)) | USBFS_UEP_R_RES_ACK; + break; + case 6: + USBFS_DEVICE->UEP6_RX_CTRL = (USBFS_DEVICE->UEP6_RX_CTRL & ~(USBFS_UEP_R_TOG | USBFS_UEP_R_RES_MASK)) | USBFS_UEP_R_RES_ACK; + break; + case 7: + USBFS_DEVICE->UEP7_RX_CTRL = (USBFS_DEVICE->UEP7_RX_CTRL & ~(USBFS_UEP_R_TOG | USBFS_UEP_R_RES_MASK)) | USBFS_UEP_R_RES_ACK; + break; + default: + break; + } + + } else { + switch (ep_idx) { + case 0: + + break; + case 1: + USBFS_DEVICE->UEP1_TX_CTRL = (USBFS_DEVICE->UEP1_TX_CTRL & ~(USBFS_UEP_T_TOG | USBFS_UEP_T_RES_MASK)) | USBFS_UEP_T_RES_NAK; + break; + case 2: + USBFS_DEVICE->UEP2_TX_CTRL = (USBFS_DEVICE->UEP2_TX_CTRL & ~(USBFS_UEP_T_TOG | USBFS_UEP_T_RES_MASK)) | USBFS_UEP_T_RES_NAK; + break; + case 3: + USBFS_DEVICE->UEP3_TX_CTRL = (USBFS_DEVICE->UEP3_TX_CTRL & ~(USBFS_UEP_T_TOG | USBFS_UEP_T_RES_MASK)) | USBFS_UEP_T_RES_NAK; + break; + case 4: + USBFS_DEVICE->UEP4_TX_CTRL = (USBFS_DEVICE->UEP4_TX_CTRL & ~(USBFS_UEP_T_TOG | USBFS_UEP_T_RES_MASK)) | USBFS_UEP_T_RES_NAK; + break; + case 5: + USBFS_DEVICE->UEP5_TX_CTRL = (USBFS_DEVICE->UEP5_TX_CTRL & ~(USBFS_UEP_T_TOG | USBFS_UEP_T_RES_MASK)) | USBFS_UEP_T_RES_NAK; + break; + case 6: + USBFS_DEVICE->UEP6_TX_CTRL = (USBFS_DEVICE->UEP6_TX_CTRL & ~(USBFS_UEP_T_TOG | USBFS_UEP_T_RES_MASK)) | USBFS_UEP_T_RES_NAK; + break; + case 7: + USBFS_DEVICE->UEP7_TX_CTRL = (USBFS_DEVICE->UEP7_TX_CTRL & ~(USBFS_UEP_T_TOG | USBFS_UEP_T_RES_MASK)) | USBFS_UEP_T_RES_NAK; + break; + default: + break; + } + } + return 0; +} +int usbd_ep_is_stalled(const uint8_t ep, uint8_t *stalled) +{ + return 0; +} + +int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (!data && data_len) { + return -1; + } + + if (!data_len) { + switch (ep_idx) { + case 0: + USBFS_DEVICE->UEP0_TX_LEN = 0; + break; + case 1: + USBFS_DEVICE->UEP1_TX_LEN = 0; + USBFS_DEVICE->UEP1_TX_CTRL = (USBFS_DEVICE->UEP1_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 2: + USBFS_DEVICE->UEP2_TX_LEN = 0; + USBFS_DEVICE->UEP2_TX_CTRL = (USBFS_DEVICE->UEP2_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 3: + USBFS_DEVICE->UEP3_TX_LEN = 0; + USBFS_DEVICE->UEP3_TX_CTRL = (USBFS_DEVICE->UEP3_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 4: + USBFS_DEVICE->UEP4_TX_LEN = 0; + USBFS_DEVICE->UEP4_TX_CTRL = (USBFS_DEVICE->UEP4_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 5: + USBFS_DEVICE->UEP5_TX_LEN = 0; + USBFS_DEVICE->UEP5_TX_CTRL = (USBFS_DEVICE->UEP5_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 6: + USBFS_DEVICE->UEP6_TX_LEN = 0; + USBFS_DEVICE->UEP6_TX_CTRL = (USBFS_DEVICE->UEP6_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 7: + USBFS_DEVICE->UEP7_TX_LEN = 0; + USBFS_DEVICE->UEP7_TX_CTRL = (USBFS_DEVICE->UEP7_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + default: + break; + } + + return 0; + } + + if (data_len > usb_dc_cfg.in_ep[ep_idx].ep_mps) { + data_len = usb_dc_cfg.in_ep[ep_idx].ep_mps; + + if (ep_idx == 0) { + mps_over_flag = 1; + } + } + + switch (ep_idx) { + case 0: + memcpy(&EP0_DatabufHD[0], data, data_len); + USBFS_DEVICE->UEP0_TX_LEN = data_len; + break; + case 1: + memcpy(&EP1_DatabufHD[64], data, data_len); + USBFS_DEVICE->UEP1_TX_LEN = data_len; + USBFS_DEVICE->UEP1_TX_CTRL = (USBFS_DEVICE->UEP1_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 2: + memcpy(&EP2_DatabufHD[64], data, data_len); + USBFS_DEVICE->UEP2_TX_LEN = data_len; + USBFS_DEVICE->UEP2_TX_CTRL = (USBFS_DEVICE->UEP2_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 3: + memcpy(&EP3_DatabufHD[64], data, data_len); + USBFS_DEVICE->UEP3_TX_LEN = data_len; + USBFS_DEVICE->UEP3_TX_CTRL = (USBFS_DEVICE->UEP3_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 4: + memcpy(&EP4_DatabufHD[64], data, data_len); + USBFS_DEVICE->UEP4_TX_LEN = data_len; + USBFS_DEVICE->UEP4_TX_CTRL = (USBFS_DEVICE->UEP4_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 5: + memcpy(&EP5_DatabufHD[64], data, data_len); + USBFS_DEVICE->UEP5_TX_LEN = data_len; + USBFS_DEVICE->UEP5_TX_CTRL = (USBFS_DEVICE->UEP5_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 6: + memcpy(&EP6_DatabufHD[64], data, data_len); + USBFS_DEVICE->UEP6_TX_LEN = data_len; + USBFS_DEVICE->UEP6_TX_CTRL = (USBFS_DEVICE->UEP6_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + case 7: + memcpy(&EP7_DatabufHD[64], data, data_len); + USBFS_DEVICE->UEP7_TX_LEN = data_len; + USBFS_DEVICE->UEP7_TX_CTRL = (USBFS_DEVICE->UEP7_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_ACK; + break; + default: + break; + } + + if (ret_bytes) { + *ret_bytes = data_len; + } + + return 0; +} + +int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes) +{ + uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint32_t read_count; + + if (!data && max_data_len) { + return -1; + } + + if (!max_data_len) { + return 0; + } + + read_count = USBFS_DEVICE->RX_LEN; + read_count = MIN(read_count, max_data_len); + + switch (ep_idx) { + case 0: + if ((max_data_len == 8) && !read_bytes) { + read_count = 8; + memcpy(data, &EP0_DatabufHD[0], 8); + } else { + memcpy(data, &EP0_DatabufHD[0], read_count); + } + break; + case 1: + memcpy(data, &EP1_DatabufHD[0], read_count); + break; + case 2: + memcpy(data, &EP2_DatabufHD[0], read_count); + break; + case 3: + memcpy(data, &EP3_DatabufHD[0], read_count); + break; + case 4: + memcpy(data, &EP4_DatabufHD[0], read_count); + break; + case 5: + memcpy(data, &EP5_DatabufHD[0], read_count); + break; + case 6: + memcpy(data, &EP6_DatabufHD[0], read_count); + break; + case 7: + memcpy(data, &EP7_DatabufHD[0], read_count); + break; + default: + break; + } + + if (read_bytes) { + *read_bytes = read_count; + } + + return 0; +} + +/********************************************************************* + * @fn OTG_FS_IRQHandler + * + * @brief This function handles OTG_FS exception. + * + * @return none + */ +void OTG_FS_IRQHandler(void) +{ + uint8_t intflag = 0; + + intflag = USBFS_DEVICE->INT_FG; + + if (intflag & USBFS_UIF_TRANSFER) { + switch (USBFS_DEVICE->INT_ST & USBFS_UIS_TOKEN_MASK) { + case USBFS_UIS_TOKEN_SETUP: + USBFS_DEVICE->UEP0_TX_CTRL = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP0_RX_CTRL = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK; + + usbd_event_notify_handler(USBD_EVENT_SETUP_NOTIFY, NULL); + + USBFS_DEVICE->UEP0_TX_CTRL = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK; + USBFS_DEVICE->UEP0_RX_CTRL = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK; + break; + + case USBFS_UIS_TOKEN_IN: + switch (USBFS_DEVICE->INT_ST & (USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK)) { + case USBFS_UIS_TOKEN_IN: + + usbd_event_notify_handler(USBD_EVENT_EP0_IN_NOTIFY, NULL); + if (usb_dc_cfg.dev_addr > 0) { + USBFS_DEVICE->DEV_ADDR = (USBFS_DEVICE->DEV_ADDR & USBFS_UDA_GP_BIT) | usb_dc_cfg.dev_addr; + usb_dc_cfg.dev_addr = 0; + } + + if (mps_over_flag) { + mps_over_flag = 0; + USBFS_DEVICE->UEP0_TX_CTRL ^= USBFS_UEP_T_TOG; + } else { + USBFS_DEVICE->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP0_RX_CTRL = USBFS_UEP_R_RES_ACK; + } + break; + + case USBFS_UIS_TOKEN_IN | 1: + USBFS_DEVICE->UEP1_TX_CTRL = (USBFS_DEVICE->UEP1_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP1_TX_CTRL ^= USBFS_UEP_T_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(1 | 0x80)); + break; + + case USBFS_UIS_TOKEN_IN | 2: + USBFS_DEVICE->UEP2_TX_CTRL = (USBFS_DEVICE->UEP2_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP2_TX_CTRL ^= USBFS_UEP_T_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(2 | 0x80)); + break; + + case USBFS_UIS_TOKEN_IN | 3: + USBFS_DEVICE->UEP3_TX_CTRL = (USBFS_DEVICE->UEP3_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP3_TX_CTRL ^= USBFS_UEP_T_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(3 | 0x80)); + break; + + case USBFS_UIS_TOKEN_IN | 4: + USBFS_DEVICE->UEP4_TX_CTRL = (USBFS_DEVICE->UEP4_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP4_TX_CTRL ^= USBFS_UEP_T_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(4 | 0x80)); + break; + + case USBFS_UIS_TOKEN_IN | 5: + USBFS_DEVICE->UEP5_TX_CTRL = (USBFS_DEVICE->UEP5_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP5_TX_CTRL ^= USBFS_UEP_T_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(5 | 0x80)); + break; + + case USBFS_UIS_TOKEN_IN | 6: + USBFS_DEVICE->UEP6_TX_CTRL = (USBFS_DEVICE->UEP6_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP6_TX_CTRL ^= USBFS_UEP_T_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(6 | 0x80)); + break; + + case USBFS_UIS_TOKEN_IN | 7: + USBFS_DEVICE->UEP7_TX_CTRL = (USBFS_DEVICE->UEP7_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP7_TX_CTRL ^= USBFS_UEP_T_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_IN_NOTIFY, (void *)(7 | 0x80)); + break; + + default: + break; + } + break; + + case USBFS_UIS_TOKEN_OUT: + switch (USBFS_DEVICE->INT_ST & (USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK)) { + case USBFS_UIS_TOKEN_OUT: + usbd_event_notify_handler(USBD_EVENT_EP0_OUT_NOTIFY, NULL); + break; + + case USBFS_UIS_TOKEN_OUT | 1: + if (USBFS_DEVICE->INT_ST & USBFS_UIS_TOG_OK) { + USBFS_DEVICE->UEP1_RX_CTRL ^= USBFS_UEP_R_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(1 & 0x7f)); + } + break; + + case USBFS_UIS_TOKEN_OUT | 2: + if (USBFS_DEVICE->INT_ST & USBFS_UIS_TOG_OK) { + USBFS_DEVICE->UEP2_RX_CTRL ^= USBFS_UEP_R_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(2 & 0x7f)); + } + break; + + case USBFS_UIS_TOKEN_OUT | 3: + if (USBFS_DEVICE->INT_ST & USBFS_UIS_TOG_OK) { + USBFS_DEVICE->UEP3_RX_CTRL ^= USBFS_UEP_R_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(3 & 0x7f)); + } + break; + + case USBFS_UIS_TOKEN_OUT | 4: + if (USBFS_DEVICE->INT_ST & USBFS_UIS_TOG_OK) { + USBFS_DEVICE->UEP4_RX_CTRL ^= USBFS_UEP_R_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(4 & 0x7f)); + } + break; + + case USBFS_UIS_TOKEN_OUT | 5: + if (USBFS_DEVICE->INT_ST & USBFS_UIS_TOG_OK) { + USBFS_DEVICE->UEP5_RX_CTRL ^= USBFS_UEP_R_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(5 & 0x7f)); + } + break; + + case USBFS_UIS_TOKEN_OUT | 6: + if (USBFS_DEVICE->INT_ST & USBFS_UIS_TOG_OK) { + USBFS_DEVICE->UEP6_RX_CTRL ^= USBFS_UEP_R_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(6 & 0x7f)); + } + break; + + case USBFS_UIS_TOKEN_OUT | 7: + if (USBFS_DEVICE->INT_ST & USBFS_UIS_TOG_OK) { + USBFS_DEVICE->UEP7_RX_CTRL ^= USBFS_UEP_R_TOG; + usbd_event_notify_handler(USBD_EVENT_EP_OUT_NOTIFY, (void *)(7 & 0x7f)); + } + break; + } + + break; + + case USBFS_UIS_TOKEN_SOF: + + break; + + default: + break; + } + + USBFS_DEVICE->INT_FG = USBFS_UIF_TRANSFER; + } else if (intflag & USBFS_UIF_BUS_RST) { + USBFS_DEVICE->DEV_ADDR = 0; + + USBFS_DEVICE->UEP0_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP1_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP2_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP3_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP4_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP5_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP6_RX_CTRL = USBFS_UEP_R_RES_ACK; + USBFS_DEVICE->UEP7_RX_CTRL = USBFS_UEP_R_RES_ACK; + + USBFS_DEVICE->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP1_TX_CTRL = USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP2_TX_CTRL = USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP3_TX_CTRL = USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP4_TX_CTRL = USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP5_TX_CTRL = USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP6_TX_CTRL = USBFS_UEP_T_RES_NAK; + USBFS_DEVICE->UEP7_TX_CTRL = USBFS_UEP_T_RES_NAK; + + usbd_event_notify_handler(USBD_EVENT_RESET, NULL); + + USBFS_DEVICE->INT_FG |= USBFS_UIF_BUS_RST; + } else if (intflag & USBFS_UIF_SUSPEND) { + if (USBFS_DEVICE->MIS_ST & USBFS_UMS_SUSPEND) { + ; + } else { + ; + } + USBFS_DEVICE->INT_FG = USBFS_UIF_SUSPEND; + } else { + USBFS_DEVICE->INT_FG = intflag; + } +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/Core/core_riscv.c b/demo/ch32/usb_device/CH32V307VCT6/Core/core_riscv.c new file mode 100644 index 00000000..786bd91e --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Core/core_riscv.c @@ -0,0 +1,380 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : core_riscv.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : RISC-V Core Peripheral Access Layer Source File +*******************************************************************************/ +#include + +/* define compiler specific symbols */ +#if defined ( __CC_ARM ) + #define __ASM __asm /*!< asm keyword for ARM Compiler */ + #define __INLINE __inline /*!< inline keyword for ARM Compiler */ + +#elif defined ( __ICCARM__ ) + #define __ASM __asm /*!< asm keyword for IAR Compiler */ + #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */ + +#elif defined ( __GNUC__ ) + #define __ASM __asm /*!< asm keyword for GNU Compiler */ + #define __INLINE inline /*!< inline keyword for GNU Compiler */ + +#elif defined ( __TASKING__ ) + #define __ASM __asm /*!< asm keyword for TASKING Compiler */ + #define __INLINE inline /*!< inline keyword for TASKING Compiler */ + +#endif + + +/** + * @brief Return the Floating-Point Accrued Exceptions + */ +uint32_t __get_FFLAGS(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "fflags" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Floating-Point Accrued Exceptions + */ +void __set_FFLAGS(uint32_t value) +{ + __ASM volatile ("csrw fflags, %0" : : "r" (value) ); +} + +/** + * @brief Return the Floating-Point Dynamic Rounding Mode + */ +uint32_t __get_FRM(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "frm" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Floating-Point Dynamic Rounding Mode + */ +void __set_FRM(uint32_t value) +{ + __ASM volatile ("csrw frm, %0" : : "r" (value) ); +} + +/** + * @brief Return the Floating-Point Control and Status Register + */ +uint32_t __get_FCSR(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "fcsr" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Floating-Point Control and Status Register + */ +void __set_FCSR(uint32_t value) +{ + __ASM volatile ("csrw fcsr, %0" : : "r" (value) ); +} + +/** + * @brief Return the Machine Status Register + */ +uint32_t __get_MSTATUS(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mstatus" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Machine Status Register + */ +void __set_MSTATUS(uint32_t value) +{ + __ASM volatile ("csrw mstatus, %0" : : "r" (value) ); +} + +/** + * @brief Return the Machine ISA Register + */ +uint32_t __get_MISA(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "misa" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Machine ISA Register + */ +void __set_MISA(uint32_t value) +{ + __ASM volatile ("csrw misa, %0" : : "r" (value) ); +} + +/** + * @brief Return the Machine Interrupt Enable Register + */ +uint32_t __get_MIE(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mie" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Machine ISA Register + */ +void __set_MIE(uint32_t value) +{ + __ASM volatile ("csrw mie, %0" : : "r" (value) ); +} + + +/** + * @brief Return the Machine Trap-Vector Base-Address Register + */ +uint32_t __get_MTVEC(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mtvec" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Machine Trap-Vector Base-Address Register + */ +void __set_MTVEC(uint32_t value) +{ + __ASM volatile ("csrw mtvec, %0" : : "r" (value) ); +} + +/** + * @brief Return the Machine Seratch Register + */ +uint32_t __get_MSCRATCH(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mscratch" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Machine Seratch Register + */ +void __set_MSCRATCH(uint32_t value) +{ + __ASM volatile ("csrw mscratch, %0" : : "r" (value) ); +} + +/** + * @brief Return the Machine Exception Program Register + */ +uint32_t __get_MEPC(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mepc" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Machine Exception Program Register + */ +void __set_MEPC(uint32_t value) +{ + __ASM volatile ("csrw mepc, %0" : : "r" (value) ); +} + +/** + * @brief Return the Machine Cause Register + */ +uint32_t __get_MCAUSE(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mcause" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Machine Cause Register + */ +void __set_MCAUSE(uint32_t value) +{ + __ASM volatile ("csrw mcause, %0" : : "r" (value) ); +} + +/** + * @brief Return the Machine Trap Value Register + */ +uint32_t __get_MTVAL(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mtval" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Machine Trap Value Register + */ +void __set_MTVAL(uint32_t value) +{ + __ASM volatile ("csrw mtval, %0" : : "r" (value) ); +} + +/** + * @brief Return the Machine Interrupt Pending Register + */ +uint32_t __get_MIP(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mip" : "=r" (result) ); + return (result); +} + +/** + * @brief Set the Machine Interrupt Pending Register + */ +void __set_MIP(uint32_t value) +{ + __ASM volatile ("csrw mip, %0" : : "r" (value) ); +} + +/** + * @brief Return Lower 32 bits of Cycle counter + */ +uint32_t __get_MCYCLE(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mcycle" : "=r" (result) ); + return (result); +} + +/** + * @brief Set Lower 32 bits of Cycle counter + */ +void __set_MCYCLE(uint32_t value) +{ + __ASM volatile ("csrw mcycle, %0" : : "r" (value) ); +} + +/** + * @brief Return Upper 32 bits of Cycle counter + */ +uint32_t __get_MCYCLEH(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mcycleh" : "=r" (result) ); + return (result); +} + +/** + * @brief Set Upper 32 bits of Cycle counter + */ +void __set_MCYCLEH(uint32_t value) +{ + __ASM volatile ("csrw mcycleh, %0" : : "r" (value) ); +} + +/** + * @brief Return Lower 32 bits of Instructions-retired counter + */ +uint32_t __get_MINSTRET(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "minstret" : "=r" (result) ); + return (result); +} + +/** + * @brief Set Lower 32 bits of Instructions-retired counter + */ +void __set_MINSTRET(uint32_t value) +{ + __ASM volatile ("csrw minstret, %0" : : "r" (value) ); +} + +/** + * @brief Return Upper 32 bits of Instructions-retired counter + */ +uint32_t __get_MINSTRETH(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "minstreth" : "=r" (result) ); + return (result); +} + +/** + * @brief Set Upper 32 bits of Instructions-retired counter + */ +void __set_MINSTRETH(uint32_t value) +{ + __ASM volatile ("csrw minstreth, %0" : : "r" (value) ); +} + +/** + * @brief Return Vendor ID Register + */ +uint32_t __get_MVENDORID(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mvendorid" : "=r" (result) ); + return (result); +} + +/** + * @brief Return Machine Architecture ID Register + */ +uint32_t __get_MARCHID(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "marchid" : "=r" (result) ); + return (result); +} + +/** + * @brief Return Machine Implementation ID Register + */ +uint32_t __get_MIMPID(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mimpid" : "=r" (result) ); + return (result); +} + +/** + * @brief Return Hart ID Register + */ +uint32_t __get_MHARTID(void) +{ + uint32_t result; + + __ASM volatile ( "csrr %0," "mhartid" : "=r" (result) ); + return (result); +} + + + diff --git a/demo/ch32/ch32v307/SRC/Core/core_riscv.h b/demo/ch32/usb_device/CH32V307VCT6/Core/core_riscv.h similarity index 62% rename from demo/ch32/ch32v307/SRC/Core/core_riscv.h rename to demo/ch32/usb_device/CH32V307VCT6/Core/core_riscv.h index 32e3dc8b..c987a3ea 100644 --- a/demo/ch32/ch32v307/SRC/Core/core_riscv.h +++ b/demo/ch32/usb_device/CH32V307VCT6/Core/core_riscv.h @@ -10,12 +10,12 @@ /* IO definitions */ #ifdef __cplusplus - #define __I volatile /* defines 'read only' permissions */ + #define __I volatile /*!< defines 'read only' permissions */ #else - #define __I volatile const /* defines 'read only' permissions */ + #define __I volatile const /*!< defines 'read only' permissions */ #endif -#define __O volatile /* defines 'write only' permissions */ -#define __IO volatile /* defines 'read / write' permissions */ +#define __O volatile /*!< defines 'write only' permissions */ +#define __IO volatile /*!< defines 'read / write' permissions */ /* Standard Peripheral Library old types (maintained for legacy purpose) */ typedef __I uint64_t vuc64; /* Read Only */ @@ -111,179 +111,125 @@ typedef struct #define SysTick ((SysTick_Type *) 0xE000F000) -/********************************************************************* - * @fn __enable_irq - * - * @brief Enable Global Interrupt - * - * @return none - */ -RV_STATIC_INLINE void __enable_irq() -{ - __asm volatile ("csrw 0x800, %0" : : "r" (0x6088) ); -} +/* risc-v specific functions */ +RV_STATIC_INLINE void __enable_irq() { __asm volatile ("csrw 0x800, %0" : : "r" (0x6088) ); } +RV_STATIC_INLINE void __disable_irq() { __asm volatile ("csrw 0x800, %0" : : "r" (0x6000) ); } +RV_STATIC_INLINE void __NOP() { __asm volatile ("nop"); } -/********************************************************************* - * @fn __disable_irq - * - * @brief Disable Global Interrupt - * - * @return none - */ -RV_STATIC_INLINE void __disable_irq() -{ - __asm volatile ("csrw 0x800, %0" : : "r" (0x6000) ); -} -/********************************************************************* - * @fn __NOP - * - * @brief nop - * - * @return none - */ -RV_STATIC_INLINE void __NOP() -{ - __asm volatile ("nop"); -} -/********************************************************************* - * @fn NVIC_EnableIRQ - * - * @brief Enable Interrupt - * - * @param IRQn: Interrupt Numbers - * - * @return none - */ -RV_STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) -{ +/* ########################## NVIC functions #################################### */ + +/******************************************************************************* +* Function Name : NVIC_EnableIRQ +* Description : Enable Interrupt +* Input : IRQn: Interrupt Numbers +* Return : None +*******************************************************************************/ +RV_STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn){ NVIC->IENR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); } -/********************************************************************* - * @fn NVIC_DisableIRQ - * - * @brief Disable Interrupt - * - * @param IRQn: Interrupt Numbers - * - * @return none - */ +/******************************************************************************* +* Function Name : NVIC_DisableIRQ +* Description : Disable Interrupt +* Input : IRQn: Interrupt Numbers +* Return : None +*******************************************************************************/ RV_STATIC_INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) { NVIC->IRER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); } -/********************************************************************* - * @fn NVIC_GetStatusIRQ - * - * @brief Get Interrupt Enable State - * - * @param IRQn: Interrupt Numbers - * - * @return 1 - Interrupt Enable - * 0 - Interrupt Disable - */ +/******************************************************************************* +* Function Name : NVIC_GetStatusIRQ +* Description : Get Interrupt Enable State +* Input : IRQn: Interrupt Numbers +* Return : 1: Interrupt Enable +* 0: Interrupt Disable +*******************************************************************************/ RV_STATIC_INLINE uint32_t NVIC_GetStatusIRQ(IRQn_Type IRQn) { return((uint32_t) ((NVIC->ISR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); } -/********************************************************************* - * @fn NVIC_GetPendingIRQ - * - * @brief Get Interrupt Pending State - * - * @param IRQn: Interrupt Numbers - * - * @return 1 - Interrupt Pending Enable - * 0 - Interrupt Pending Disable - */ +/******************************************************************************* +* Function Name : NVIC_GetPendingIRQ +* Description : Get Interrupt Pending State +* Input : IRQn: Interrupt Numbers +* Return : 1: Interrupt Pending Enable +* 0: Interrupt Pending Disable +*******************************************************************************/ RV_STATIC_INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) { return((uint32_t) ((NVIC->IPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); } -/********************************************************************* - * @fn NVIC_SetPendingIRQ - * - * @brief Set Interrupt Pending - * - * @param IRQn: Interrupt Numbers - * - * @return None - */ +/******************************************************************************* +* Function Name : NVIC_SetPendingIRQ +* Description : Set Interrupt Pending +* Input : IRQn: Interrupt Numbers +* Return : None +*******************************************************************************/ RV_STATIC_INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) { NVIC->IPSR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); } -/********************************************************************* - * @fn NVIC_ClearPendingIRQ - * - * @brief Clear Interrupt Pending - * - * @param IRQn: Interrupt Numbers - * - * @return None - */ +/******************************************************************************* +* Function Name : NVIC_ClearPendingIRQ +* Description : Clear Interrupt Pending +* Input : IRQn: Interrupt Numbers +* Return : None +*******************************************************************************/ RV_STATIC_INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) { NVIC->IPRR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); } -/********************************************************************* - * @fn NVIC_GetActive - * - * @brief Get Interrupt Active State - * - * @param IRQn: Interrupt Numbers - * - * @return 1 - Interrupt Active - * 0 - Interrupt No Active - */ +/******************************************************************************* +* Function Name : NVIC_GetActive +* Description : Get Interrupt Active State +* Input : IRQn: Interrupt Numbers +* Return : 1: Interrupt Active +* 0: Interrupt No Active +*******************************************************************************/ RV_STATIC_INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) { return((uint32_t)((NVIC->IACTR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); } -/********************************************************************* - * @fn NVIC_SetPriority - * - * @brief Set Interrupt Priority - * - * @param IRQn - Interrupt Numbers - * priority - - * bit7 - pre-emption priority - * bit6~bit4 - subpriority - * @return None - */ +/******************************************************************************* +* Function Name : NVIC_SetPriority +* Description : Set Interrupt Priority +* Input : IRQn: Interrupt Numbers +* priority: bit7:pre-emption priority +* bit6-bit4: subpriority +* Return : None +*******************************************************************************/ RV_STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint8_t priority) { NVIC->IPRIOR[(uint32_t)(IRQn)] = priority; } -/********************************************************************* - * @fn __WFI - * - * @brief Wait for Interrupt - * - * @return None - */ +/******************************************************************************* +* Function Name : __WFI +* Description : Wait for Interrupt +* Input : None +* Return : None +*******************************************************************************/ __attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFI(void) { NVIC->SCTLR &= ~(1<<3); // wfi asm volatile ("wfi"); } -/********************************************************************* - * @fn __WFE - * - * @brief Wait for Events - * - * @return None - */ +/******************************************************************************* +* Function Name : __WFE +* Description : Wait for Events +* Input : None +* Return : None +*******************************************************************************/ __attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void) { uint32_t t; @@ -295,44 +241,42 @@ __attribute__( ( always_inline ) ) RV_STATIC_INLINE void __WFE(void) asm volatile ("wfi"); } -/********************************************************************* - * @fn SetVTFIRQ - * - * @brief Set VTF Interrupt - * - * @param add - VTF interrupt service function base address. - * IRQn -Interrupt Numbers - * num - VTF Interrupt Numbers - * NewState - DISABLE or ENABLE - * @return None - */ +/******************************************************************************* +* Function Name : SetVTFIRQ +* Description : Set VTF Interrupt +* Input : addrVTF interrupt service function base address. +* IRQnInterrupt Numbers +* numVTF Interrupt Numbers +* NewState: DISABLE or ENABLE +* Return : None +*******************************************************************************/ RV_STATIC_INLINE void SetVTFIRQ(uint32_t addr, IRQn_Type IRQn, uint8_t num, FunctionalState NewState){ if(num > 3) return ; if (NewState != DISABLE) { NVIC->VTFIDR[num] = IRQn; - NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)|0x1); + NVIC->VTFADDR[num] = ((addr&0xF00FFFFE)|0x1); } else{ NVIC->VTFIDR[num] = IRQn; - NVIC->VTFADDR[num] = ((addr&0xFFFFFFFE)&(~0x1)); + NVIC->VTFADDR[num] = ((addr&0xF00FFFFE)&(~0x1)); } } -/********************************************************************* - * @fn NVIC_SystemReset - * - * @brief Initiate a system reset request - * - * @return None - */ +/******************************************************************************* +* Function Name : NVIC_SystemReset +* Description : Initiate a system reset request +* Input : None +* Return : None +*******************************************************************************/ RV_STATIC_INLINE void NVIC_SystemReset(void) { NVIC->CFGR = NVIC_KEY3|(1<<7); } + /* Core_Exported_Functions */ extern uint32_t __get_FFLAGS(void); extern void __set_FFLAGS(uint32_t value); diff --git a/demo/ch32/ch32v307/SRC/Debug/debug.c b/demo/ch32/usb_device/CH32V307VCT6/Debug/debug.c similarity index 74% rename from demo/ch32/ch32v307/SRC/Debug/debug.c rename to demo/ch32/usb_device/CH32V307VCT6/Debug/debug.c index be47839a..4c88f79e 100644 --- a/demo/ch32/ch32v307/SRC/Debug/debug.c +++ b/demo/ch32/usb_device/CH32V307VCT6/Debug/debug.c @@ -11,28 +11,24 @@ static uint8_t p_us=0; static uint16_t p_ms=0; -/********************************************************************* - * @fn Delay_Init - * - * @brief Initializes Delay Funcation. - * - * @return none - */ +/******************************************************************************* +* Function Name : Delay_Init +* Description : Initializes Delay Funcation. +* Input : None +* Return : None +*******************************************************************************/ void Delay_Init(void) { p_us=SystemCoreClock/8000000; p_ms=(uint16_t)p_us*1000; } -/********************************************************************* - * @fn Delay_Us - * - * @brief Microsecond Delay Time. - * - * @param n - Microsecond number. - * - * @return None - */ +/******************************************************************************* +* Function Name : Delay_Us +* Description : Microsecond Delay Time. +* Input : nMicrosecond number. +* Return : None +*******************************************************************************/ void Delay_Us(uint32_t n) { uint32_t i; @@ -47,15 +43,12 @@ void Delay_Us(uint32_t n) SysTick->SR &= ~(1<<0); } -/********************************************************************* - * @fn Delay_Ms - * - * @brief Millisecond Delay Time. - * - * @param n - Millisecond number. - * - * @return None - */ +/******************************************************************************* +* Function Name : Delay_Ms +* Description : Millisecond Delay Time. +* Input : nMillisecond number. +* Return : None +*******************************************************************************/ void Delay_Ms(uint32_t n) { uint32_t i; @@ -70,15 +63,12 @@ void Delay_Ms(uint32_t n) SysTick->SR &= ~(1<<0); } -/********************************************************************* - * @fn USART_Printf_Init - * - * @brief Initializes the USARTx peripheral. - * - * @param baudrate - USART communication baud rate. - * - * @return None - */ +/******************************************************************************* +* Function Name : USART_Printf_Init +* Description : Initializes the USARTx peripheral. +* Input : baudrate: USART communication baud rate. +* Return : None +*******************************************************************************/ void USART_Printf_Init(uint32_t baudrate) { GPIO_InitTypeDef GPIO_InitStructure; @@ -134,16 +124,13 @@ void USART_Printf_Init(uint32_t baudrate) #endif } -/********************************************************************* - * @fn _write - * - * @brief Support Printf Function - * - * @param *buf - UART send Data. - * size - Data length - * - * @return size: Data length - */ +/******************************************************************************* +* Function Name : _write +* Description : Support Printf Function +* Input : *buf: UART send Data. +* size: Data length +* Return : size: Data length +*******************************************************************************/ int _write(int fd, char *buf, int size) { int i; diff --git a/demo/ch32/ch32v307/SRC/Debug/debug.h b/demo/ch32/usb_device/CH32V307VCT6/Debug/debug.h similarity index 100% rename from demo/ch32/ch32v307/SRC/Debug/debug.h rename to demo/ch32/usb_device/CH32V307VCT6/Debug/debug.h diff --git a/demo/ch32/ch32v307/SRC/Ld/Link.ld b/demo/ch32/usb_device/CH32V307VCT6/Ld/Link.ld similarity index 100% rename from demo/ch32/ch32v307/SRC/Ld/Link.ld rename to demo/ch32/usb_device/CH32V307VCT6/Ld/Link.ld diff --git a/demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x.h similarity index 97% rename from demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x.h rename to demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x.h index cbcdf579..2c244a95 100644 --- a/demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x.h +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x.h @@ -309,7 +309,7 @@ typedef struct uint32_t RESERVED4; __IO uint32_t FWR; uint32_t RESERVED5[8]; - CAN_FilterRegister_TypeDef sFilterRegister[28]; + CAN_FilterRegister_TypeDef sFilterRegister[14]; } CAN_TypeDef; /* CRC Calculation Unit */ @@ -425,6 +425,27 @@ typedef struct __IO uint32_t ECCR2; } FSMC_Bank2_TypeDef; +/* FSMC Bank3 Registers */ +typedef struct +{ + __IO uint32_t PCR3; + __IO uint32_t SR3; + __IO uint32_t PMEM3; + __IO uint32_t PATT3; + uint32_t RESERVED0; + __IO uint32_t ECCR3; +} FSMC_Bank3_TypeDef; + +/* FSMC Bank4 Registers */ +typedef struct +{ + __IO uint32_t PCR4; + __IO uint32_t SR4; + __IO uint32_t PMEM4; + __IO uint32_t PATT4; + __IO uint32_t PIO4; +} FSMC_Bank4_TypeDef; + /* General Purpose I/O */ typedef struct { @@ -695,19 +716,10 @@ typedef struct /* USBHS Registers */ typedef struct { - __IO uint8_t CONTROL; - __IO uint8_t HOST_CTRL; - __IO uint8_t INT_EN; - __IO uint8_t DEV_AD; - __IO uint16_t FRAME_NO; - __IO uint8_t SUSPEND; - __IO uint8_t RESERVED0; - __IO uint8_t SPEED_TYPE; - __IO uint8_t MIS_ST; - __IO uint8_t INT_FG; - __IO uint8_t INT_ST; - __IO uint16_t RX_LEN; - __IO uint16_t RESERVED1; + __IO uint32_t CONTROL; + __IO uint32_t FRAME_NO; + __IO uint32_t STATUS; + __IO uint32_t RX_LEN; __IO uint32_t ENDP_CONFIG; __IO uint32_t ENDP_TYPE; __IO uint32_t BUF_MODE; @@ -742,166 +754,39 @@ typedef struct __IO uint32_t UEP13_TX_DMA; __IO uint32_t UEP14_TX_DMA; __IO uint32_t UEP15_TX_DMA; - __IO uint16_t UEP0_MAX_LEN; - __IO uint16_t RESERVED2; - __IO uint16_t UEP1_MAX_LEN; - __IO uint16_t RESERVED3; - __IO uint16_t UEP2_MAX_LEN; - __IO uint16_t RESERVED4; - __IO uint16_t UEP3_MAX_LEN; - __IO uint16_t RESERVED5; - __IO uint16_t UEP4_MAX_LEN; - __IO uint16_t RESERVED6; - __IO uint16_t UEP5_MAX_LEN; - __IO uint16_t RESERVED7; - __IO uint16_t UEP6_MAX_LEN; - __IO uint16_t RESERVED8; - __IO uint16_t UEP7_MAX_LEN; - __IO uint16_t RESERVED9; - __IO uint16_t UEP8_MAX_LEN; - __IO uint16_t RESERVED10; - __IO uint16_t UEP9_MAX_LEN; - __IO uint16_t RESERVED11; - __IO uint16_t UEP10_MAX_LEN; - __IO uint16_t RESERVED12; - __IO uint16_t UEP11_MAX_LEN; - __IO uint16_t RESERVED13; - __IO uint16_t UEP12_MAX_LEN; - __IO uint16_t RESERVED14; - __IO uint16_t UEP13_MAX_LEN; - __IO uint16_t RESERVED15; - __IO uint16_t UEP14_MAX_LEN; - __IO uint16_t RESERVED16; - __IO uint16_t UEP15_MAX_LEN; - __IO uint16_t RESERVED17; - __IO uint16_t UEP0_TX_LEN; - __IO uint8_t UEP0_TX_CTRL; - __IO uint8_t UEP0_RX_CTRL; - __IO uint16_t UEP1_TX_LEN; - __IO uint8_t UEP1_TX_CTRL; - __IO uint8_t UEP1_RX_CTRL; - __IO uint16_t UEP2_TX_LEN; - __IO uint8_t UEP2_TX_CTRL; - __IO uint8_t UEP2_RX_CTRL; - __IO uint16_t UEP3_TX_LEN; - __IO uint8_t UEP3_TX_CTRL; - __IO uint8_t UEP3_RX_CTRL; - __IO uint16_t UEP4_TX_LEN; - __IO uint8_t UEP4_TX_CTRL; - __IO uint8_t UEP4_RX_CTRL; - __IO uint16_t UEP5_TX_LEN; - __IO uint8_t UEP5_TX_CTRL; - __IO uint8_t UEP5_RX_CTRL; - __IO uint16_t UEP6_TX_LEN; - __IO uint8_t UEP6_TX_CTRL; - __IO uint8_t UEP6_RX_CTRL; - __IO uint16_t UEP7_TX_LEN; - __IO uint8_t UEP7_TX_CTRL; - __IO uint8_t UEP7_RX_CTRL; - __IO uint16_t UEP8_TX_LEN; - __IO uint8_t UEP8_TX_CTRL; - __IO uint8_t UEP8_RX_CTRL; - __IO uint16_t UEP9_TX_LEN; - __IO uint8_t UEP9_TX_CTRL; - __IO uint8_t UEP9_RX_CTRL; - __IO uint16_t UEP10_TX_LEN; - __IO uint8_t UEP10_TX_CTRL; - __IO uint8_t UEP10_RX_CTRL; - __IO uint16_t UEP11_TX_LEN; - __IO uint8_t UEP11_TX_CTRL; - __IO uint8_t UEP11_RX_CTRL; - __IO uint16_t UEP12_TX_LEN; - __IO uint8_t UEP12_TX_CTRL; - __IO uint8_t UEP12_RX_CTRL; - __IO uint16_t UEP13_TX_LEN; - __IO uint8_t UEP13_TX_CTRL; - __IO uint8_t UEP13_RX_CTRL; - __IO uint16_t UEP14_TX_LEN; - __IO uint8_t UEP14_TX_CTRL; - __IO uint8_t UEP14_RX_CTRL; - __IO uint16_t UEP15_TX_LEN; - __IO uint8_t UEP15_TX_CTRL; - __IO uint8_t UEP15_RX_CTRL; -} USBHSD_TypeDef; - -typedef struct __attribute__((packed)) -{ - __IO uint8_t CONTROL; - __IO uint8_t HOST_CTRL; - __IO uint8_t INT_EN; - __IO uint8_t DEV_AD; - __IO uint16_t FRAME_NO; - __IO uint8_t SUSPEND; - __IO uint8_t RESERVED0; - __IO uint8_t SPEED_TYPE; - __IO uint8_t MIS_ST; - __IO uint8_t INT_FG; - __IO uint8_t INT_ST; - __IO uint16_t RX_LEN; - __IO uint16_t RESERVED1; - __IO uint32_t HOST_EP_CONFIG; - __IO uint32_t HOST_EP_TYPE; - __IO uint32_t RESERVED2; - __IO uint32_t RESERVED3; - __IO uint32_t RESERVED4; - __IO uint32_t HOST_RX_DMA; - __IO uint32_t RESERVED5; - __IO uint32_t RESERVED6; - __IO uint32_t RESERVED7; - __IO uint32_t RESERVED8; - __IO uint32_t RESERVED9; - __IO uint32_t RESERVED10; - __IO uint32_t RESERVED11; - __IO uint32_t RESERVED12; - __IO uint32_t RESERVED13; - __IO uint32_t RESERVED14; - __IO uint32_t RESERVED15; - __IO uint32_t RESERVED16; - __IO uint32_t RESERVED17; - __IO uint32_t RESERVED18; - __IO uint32_t RESERVED19; - __IO uint32_t HOST_TX_DMA; - __IO uint32_t RESERVED20; - __IO uint32_t RESERVED21; - __IO uint32_t RESERVED22; - __IO uint32_t RESERVED23; - __IO uint32_t RESERVED24; - __IO uint32_t RESERVED25; - __IO uint32_t RESERVED26; - __IO uint32_t RESERVED27; - __IO uint32_t RESERVED28; - __IO uint32_t RESERVED29; - __IO uint32_t RESERVED30; - __IO uint32_t RESERVED31; - __IO uint32_t RESERVED32; - __IO uint32_t RESERVED33; - __IO uint16_t HOST_RX_MAX_LEN; - __IO uint16_t RESERVED34; - __IO uint32_t RESERVED35; - __IO uint32_t RESERVED36; - __IO uint32_t RESERVED37; - __IO uint32_t RESERVED38; - __IO uint32_t RESERVED39; - __IO uint32_t RESERVED40; - __IO uint32_t RESERVED41; - __IO uint32_t RESERVED42; - __IO uint32_t RESERVED43; - __IO uint32_t RESERVED44; - __IO uint32_t RESERVED45; - __IO uint32_t RESERVED46; - __IO uint32_t RESERVED47; - __IO uint32_t RESERVED48; - __IO uint32_t RESERVED49; - __IO uint8_t HOST_EP_PID; - __IO uint8_t RESERVED50; - __IO uint8_t RESERVED51; - __IO uint8_t HOST_RX_CTRL; - __IO uint16_t HOST_TX_LEN; - __IO uint8_t HOST_TX_CTRL; - __IO uint8_t RESERVED52; - __IO uint16_t HOST_SPLIT_DATA; -} USBHSH_TypeDef; - + __IO uint32_t UEP0_MAX_LEN; + __IO uint32_t UEP1_MAX_LEN; + __IO uint32_t UEP2_MAX_LEN; + __IO uint32_t UEP3_MAX_LEN; + __IO uint32_t UEP4_MAX_LEN; + __IO uint32_t UEP5_MAX_LEN; + __IO uint32_t UEP6_MAX_LEN; + __IO uint32_t UEP7_MAX_LEN; + __IO uint32_t UEP8_MAX_LEN; + __IO uint32_t UEP9_MAX_LEN; + __IO uint32_t UEP10_MAX_LEN; + __IO uint32_t UEP11_MAX_LEN; + __IO uint32_t UEP12_MAX_LEN; + __IO uint32_t UEP13_MAX_LEN; + __IO uint32_t UEP14_MAX_LEN; + __IO uint32_t UEP15_MAX_LEN; + __IO uint32_t UEP0_CTRL; + __IO uint32_t UEP1_CTRL; + __IO uint32_t UEP2_CTRL; + __IO uint32_t UEP3_CTRL; + __IO uint32_t UEP4_CTRL; + __IO uint32_t UEP5_CTRL; + __IO uint32_t UEP6_CTRL; + __IO uint32_t UEP7_CTRL; + __IO uint32_t UEP8_CTRL; + __IO uint32_t UEP9_CTRL; + __IO uint32_t UEP10_CTRL; + __IO uint32_t UEP11_CTRL; + __IO uint32_t UEP12_CTRL; + __IO uint32_t UEP13_CTRL; + __IO uint32_t UEP14_CTRL; + __IO uint32_t UEP15_CTRL; +} USBHS_TypeDef; /* USBOTG_FS Registers */ typedef struct @@ -914,8 +799,7 @@ typedef struct __IO uint8_t MIS_ST; __IO uint8_t INT_FG; __IO uint8_t INT_ST; - __IO uint16_t RX_LEN; - __IO uint16_t Reserve1; + __IO uint32_t RX_LEN; __IO uint8_t UEP4_1_MOD; __IO uint8_t UEP2_3_MOD; __IO uint8_t UEP5_6_MOD; @@ -952,53 +836,11 @@ typedef struct __IO uint16_t UEP7_TX_LEN; __IO uint8_t UEP7_TX_CTRL; __IO uint8_t UEP7_RX_CTRL; - __IO uint32_t Reserve2; + __IO uint32_t Reserve1; __IO uint32_t OTG_CR; __IO uint32_t OTG_SR; }USBOTG_FS_TypeDef; -typedef struct __attribute__((packed)) -{ - __IO uint8_t BASE_CTRL; - __IO uint8_t HOST_CTRL; - __IO uint8_t INT_EN; - __IO uint8_t DEV_ADDR; - __IO uint8_t Reserve0; - __IO uint8_t MIS_ST; - __IO uint8_t INT_FG; - __IO uint8_t INT_ST; - __IO uint16_t RX_LEN; - __IO uint16_t Reserve1; - __IO uint8_t Reserve2; - __IO uint8_t HOST_EP_MOD; - __IO uint16_t Reserve3; - __IO uint32_t Reserve4; - __IO uint32_t Reserve5; - __IO uint32_t HOST_RX_DMA; - __IO uint32_t HOST_TX_DMA; - __IO uint32_t Reserve6; - __IO uint32_t Reserve7; - __IO uint32_t Reserve8; - __IO uint32_t Reserve9; - __IO uint32_t Reserve10; - __IO uint16_t Reserve11; - __IO uint16_t HOST_SETUP; - __IO uint8_t HOST_EP_PID; - __IO uint8_t Reserve12; - __IO uint8_t Reserve13; - __IO uint8_t HOST_RX_CTRL; - __IO uint16_t HOST_TX_LEN; - __IO uint8_t HOST_TX_CTRL; - __IO uint8_t Reserve14; - __IO uint32_t Reserve15; - __IO uint32_t Reserve16; - __IO uint32_t Reserve17; - __IO uint32_t Reserve18; - __IO uint32_t Reserve19; - __IO uint32_t OTG_CR; - __IO uint32_t OTG_SR; -}USBOTGH_FS_TypeDef; - /* Ethernet MAC */ typedef struct { @@ -1172,6 +1014,8 @@ typedef struct #define FSMC_Bank1_R_BASE (FSMC_R_BASE + 0x0000) #define FSMC_Bank1E_R_BASE (FSMC_R_BASE + 0x0104) #define FSMC_Bank2_R_BASE (FSMC_R_BASE + 0x0060) +#define FSMC_Bank3_R_BASE (FSMC_R_BASE + 0x0080) +#define FSMC_Bank4_R_BASE (FSMC_R_BASE + 0x00A0) #define DBGMCU_BASE ((uint32_t)0xE000D000) @@ -1254,10 +1098,8 @@ typedef struct #define RCC ((RCC_TypeDef *) RCC_BASE) #define FLASH ((FLASH_TypeDef *) FLASH_R_BASE) #define CRC ((CRC_TypeDef *) CRC_BASE) -#define USBHSD ((USBHSD_TypeDef *) USBHS_BASE) -#define USBHSH ((USBHSH_TypeDef *) USBHS_BASE) -#define USBOTG_FS ((USBOTG_FS_TypeDef *)USBFS_BASE) -#define USBOTG_H_FS ((USBOTGH_FS_TypeDef *)USBFS_BASE) +#define USBHS ((USBHS_TypeDef *) USBHS_BASE) +#define USBOTG_FS ((USBOTG_FS_TypeDef *) USBFS_BASE) #define EXTEN ((EXTEN_TypeDef *) EXTEN_BASE) #define OPA ((OPA_TypeDef *) OPA_BASE) #define RNG ((RNG_TypeDef *) RNG_BASE) @@ -1268,6 +1110,8 @@ typedef struct #define FSMC_Bank1 ((FSMC_Bank1_TypeDef *) FSMC_Bank1_R_BASE) #define FSMC_Bank1E ((FSMC_Bank1E_TypeDef *) FSMC_Bank1E_R_BASE) #define FSMC_Bank2 ((FSMC_Bank2_TypeDef *) FSMC_Bank2_R_BASE) +#define FSMC_Bank3 ((FSMC_Bank3_TypeDef *) FSMC_Bank3_R_BASE) +#define FSMC_Bank4 ((FSMC_Bank4_TypeDef *) FSMC_Bank4_R_BASE) #define DBGMCU ((DBGMCU_TypeDef *) DBGMCU_BASE) @@ -3079,26 +2923,26 @@ typedef struct #define DAC_DMAEN2 ((uint32_t)0x10000000) /* DAC channel2 DMA enabled */ /***************** Bit definition for DAC_SWTR register ******************/ -#define DAC_SWTRIG1 ((uint8_t)0x01) /* DAC channel1 software trigger */ -#define DAC_SWTRIG2 ((uint8_t)0x02) /* DAC channel2 software trigger */ +#define DAC_SWTRIG1 ((uint8_t)0x01) /* DAC channel1 software trigger */ +#define DAC_SWTRIG2 ((uint8_t)0x02) /* DAC channel2 software trigger */ /***************** Bit definition for DAC_R12BDHR1 register ******************/ -#define DAC_DHR12R1 ((uint16_t)0x0FFF) /* DAC channel1 12-bit Right aligned data */ +#define DAC_DHR12R1 ((uint16_t)0x0FFF) /* DAC channel1 12-bit Right aligned data */ /***************** Bit definition for DAC_L12BDHR1 register ******************/ -#define DAC_DHR12L1 ((uint16_t)0xFFF0) /* DAC channel1 12-bit Left aligned data */ +#define DAC_DHR12L1 ((uint16_t)0xFFF0) /* DAC channel1 12-bit Left aligned data */ /****************** Bit definition for DAC_R8BDHR1 register ******************/ -#define DAC_DHR8R1 ((uint8_t)0xFF) /* DAC channel1 8-bit Right aligned data */ +#define DAC_DHR8R1 ((uint8_t)0xFF) /* DAC channel1 8-bit Right aligned data */ /***************** Bit definition for DAC_R12BDHR2 register ******************/ -#define DAC_DHR12R2 ((uint16_t)0x0FFF) /* DAC channel2 12-bit Right aligned data */ +#define DAC_DHR12R2 ((uint16_t)0x0FFF) /* DAC channel2 12-bit Right aligned data */ /***************** Bit definition for DAC_L12BDHR2 register ******************/ -#define DAC_DHR12L2 ((uint16_t)0xFFF0) /* DAC channel2 12-bit Left aligned data */ +#define DAC_DHR12L2 ((uint16_t)0xFFF0) /* DAC channel2 12-bit Left aligned data */ /****************** Bit definition for DAC_R8BDHR2 register ******************/ -#define DAC_DHR8R2 ((uint8_t)0xFF) /* DAC channel2 8-bit Right aligned data */ +#define DAC_DHR8R2 ((uint8_t)0xFF) /* DAC channel2 8-bit Right aligned data */ /***************** Bit definition for DAC_RD12BDHR register ******************/ #define DAC_RD12BDHR_DACC1DHR ((uint32_t)0x00000FFF) /* DAC channel1 12-bit Right aligned data */ @@ -3160,14 +3004,14 @@ typedef struct #define DMA_TCIF9 ((uint32_t)0x00000020) /* Channel 9 Transfer Complete flag */ #define DMA_HTIF9 ((uint32_t)0x00000040) /* Channel 9 Half Transfer flag */ #define DMA_TEIF9 ((uint32_t)0x00000080) /* Channel 9 Transfer Error flag */ -#define DMA_GIF10 ((uint32_t)0x00000100) /* Channel 10 Global interrupt flag */ -#define DMA_TCIF10 ((uint32_t)0x00000200) /* Channel 10 Transfer Complete flag */ -#define DMA_HTIF10 ((uint32_t)0x00000400) /* Channel 10 Half Transfer flag */ -#define DMA_TEIF10 ((uint32_t)0x00000800) /* Channel 10 Transfer Error flag */ -#define DMA_GIF11 ((uint32_t)0x00001000) /* Channel 11 Global interrupt flag */ -#define DMA_TCIF11 ((uint32_t)0x00002000) /* Channel 11 Transfer Complete flag */ -#define DMA_HTIF11 ((uint32_t)0x00004000) /* Channel 11 Half Transfer flag */ -#define DMA_TEIF11 ((uint32_t)0x00008000) /* Channel 11 Transfer Error flag */ +#define DMA_GIF10 ((uint32_t)0x00000100) /* Channel 10 Global interrupt flag */ +#define DMA_TCIF10 ((uint32_t)0x00000200) /* Channel 10 Transfer Complete flag */ +#define DMA_HTIF10 ((uint32_t)0x00000400) /* Channel 10 Half Transfer flag */ +#define DMA_TEIF10 ((uint32_t)0x00000800) /* Channel 10 Transfer Error flag */ +#define DMA_GIF11 ((uint32_t)0x00001000) /* Channel 11 Global interrupt flag */ +#define DMA_TCIF11 ((uint32_t)0x00002000) /* Channel 11 Transfer Complete flag */ +#define DMA_HTIF11 ((uint32_t)0x00004000) /* Channel 11 Half Transfer flag */ +#define DMA_TEIF11 ((uint32_t)0x00008000) /* Channel 11 Transfer Error flag */ /******************* Bit definition for DMA_INTFCR register *******************/ #define DMA_CGIF1 ((uint32_t)0x00000001) /* Channel 1 Global interrupt clear */ @@ -3573,6 +3417,14 @@ typedef struct /******************* Bit definition for FLASH_ACTLR register ******************/ +#define FLASH_ACTLR_LATENCY ((uint8_t)0x03) /* LATENCY[2:0] bits (Latency) */ +#define FLASH_ACTLR_LATENCY_0 ((uint8_t)0x00) /* Bit 0 */ +#define FLASH_ACTLR_LATENCY_1 ((uint8_t)0x01) /* Bit 0 */ +#define FLASH_ACTLR_LATENCY_2 ((uint8_t)0x02) /* Bit 1 */ + +#define FLASH_ACTLR_HLFCYA ((uint8_t)0x08) /* Flash Half Cycle Access Enable */ +#define FLASH_ACTLR_PRFTBE ((uint8_t)0x10) /* Prefetch Buffer Enable */ +#define FLASH_ACTLR_PRFTBS ((uint8_t)0x20) /* Prefetch Buffer Status */ /****************** Bit definition for FLASH_KEYR register ******************/ #define FLASH_KEYR_FKEYR ((uint32_t)0xFFFFFFFF) /* FPEC Key */ @@ -4163,20 +4015,20 @@ typedef struct /******************************************************************************/ /******************* Bit definition for IWDG_CTLR register ********************/ -#define IWDG_KEY ((uint16_t)0xFFFF) /* Key value (write only, read 0000h) */ +#define IWDG_KEY ((uint16_t)0xFFFF) /* Key value (write only, read 0000h) */ /******************* Bit definition for IWDG_PSCR register ********************/ -#define IWDG_PR ((uint8_t)0x07) /* PR[2:0] (Prescaler divider) */ -#define IWDG_PR_0 ((uint8_t)0x01) /* Bit 0 */ -#define IWDG_PR_1 ((uint8_t)0x02) /* Bit 1 */ -#define IWDG_PR_2 ((uint8_t)0x04) /* Bit 2 */ +#define IWDG_PR ((uint8_t)0x07) /* PR[2:0] (Prescaler divider) */ +#define IWDG_PR_0 ((uint8_t)0x01) /* Bit 0 */ +#define IWDG_PR_1 ((uint8_t)0x02) /* Bit 1 */ +#define IWDG_PR_2 ((uint8_t)0x04) /* Bit 2 */ /******************* Bit definition for IWDG_RLDR register *******************/ -#define IWDG_RL ((uint16_t)0x0FFF) /* Watchdog counter reload value */ +#define IWDG_RL ((uint16_t)0x0FFF) /* Watchdog counter reload value */ /******************* Bit definition for IWDG_STATR register ********************/ -#define IWDG_PVU ((uint8_t)0x01) /* Watchdog prescaler value update */ -#define IWDG_RVU ((uint8_t)0x02) /* Watchdog counter reload value update */ +#define IWDG_PVU ((uint8_t)0x01) /* Watchdog prescaler value update */ +#define IWDG_RVU ((uint8_t)0x02) /* Watchdog counter reload value update */ /******************************************************************************/ /* Inter-integrated Circuit Interface */ diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_adc.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_adc.h new file mode 100644 index 00000000..e0960f67 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_adc.h @@ -0,0 +1,226 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_adc.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* ADC firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_ADC_H +#define __CH32V30x_ADC_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + + +/* ADC Init structure definition */ +typedef struct +{ + uint32_t ADC_Mode; /* Configures the ADC to operate in independent or + dual mode. + This parameter can be a value of @ref ADC_mode */ + + FunctionalState ADC_ScanConvMode; /* Specifies whether the conversion is performed in + Scan (multichannels) or Single (one channel) mode. + This parameter can be set to ENABLE or DISABLE */ + + FunctionalState ADC_ContinuousConvMode; /* Specifies whether the conversion is performed in + Continuous or Single mode. + This parameter can be set to ENABLE or DISABLE. */ + + uint32_t ADC_ExternalTrigConv; /* Defines the external trigger used to start the analog + to digital conversion of regular channels. This parameter + can be a value of @ref ADC_external_trigger_sources_for_regular_channels_conversion */ + + uint32_t ADC_DataAlign; /* Specifies whether the ADC data alignment is left or right. + This parameter can be a value of @ref ADC_data_align */ + + uint8_t ADC_NbrOfChannel; /* Specifies the number of ADC channels that will be converted + using the sequencer for regular channel group. + This parameter must range from 1 to 16. */ + + uint32_t ADC_OutputBuffer; /* Specifies whether the ADC channel output buffer is enabled or disabled. + This parameter can be a value of @ref ADC_OutputBuffer */ + + uint32_t ADC_Pga; /* Specifies the PGA gain multiple. + This parameter can be a value of @ref ADC_Pga */ +}ADC_InitTypeDef; + +/* ADC_mode */ +#define ADC_Mode_Independent ((uint32_t)0x00000000) +#define ADC_Mode_RegInjecSimult ((uint32_t)0x00010000) +#define ADC_Mode_RegSimult_AlterTrig ((uint32_t)0x00020000) +#define ADC_Mode_InjecSimult_FastInterl ((uint32_t)0x00030000) +#define ADC_Mode_InjecSimult_SlowInterl ((uint32_t)0x00040000) +#define ADC_Mode_InjecSimult ((uint32_t)0x00050000) +#define ADC_Mode_RegSimult ((uint32_t)0x00060000) +#define ADC_Mode_FastInterl ((uint32_t)0x00070000) +#define ADC_Mode_SlowInterl ((uint32_t)0x00080000) +#define ADC_Mode_AlterTrig ((uint32_t)0x00090000) + +/* ADC_external_trigger_sources_for_regular_channels_conversion */ +#define ADC_ExternalTrigConv_T1_CC1 ((uint32_t)0x00000000) +#define ADC_ExternalTrigConv_T1_CC2 ((uint32_t)0x00020000) +#define ADC_ExternalTrigConv_T2_CC2 ((uint32_t)0x00060000) +#define ADC_ExternalTrigConv_T3_TRGO ((uint32_t)0x00080000) +#define ADC_ExternalTrigConv_T4_CC4 ((uint32_t)0x000A0000) +#define ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO ((uint32_t)0x000C0000) + +#define ADC_ExternalTrigConv_T1_CC3 ((uint32_t)0x00040000) +#define ADC_ExternalTrigConv_None ((uint32_t)0x000E0000) + +#define ADC_ExternalTrigConv_T3_CC1 ((uint32_t)0x00000000) +#define ADC_ExternalTrigConv_T2_CC3 ((uint32_t)0x00020000) +#define ADC_ExternalTrigConv_T8_CC1 ((uint32_t)0x00060000) +#define ADC_ExternalTrigConv_T8_TRGO ((uint32_t)0x00080000) +#define ADC_ExternalTrigConv_T5_CC1 ((uint32_t)0x000A0000) +#define ADC_ExternalTrigConv_T5_CC3 ((uint32_t)0x000C0000) + + +/* ADC_data_align */ +#define ADC_DataAlign_Right ((uint32_t)0x00000000) +#define ADC_DataAlign_Left ((uint32_t)0x00000800) + +/* ADC_channels */ +#define ADC_Channel_0 ((uint8_t)0x00) +#define ADC_Channel_1 ((uint8_t)0x01) +#define ADC_Channel_2 ((uint8_t)0x02) +#define ADC_Channel_3 ((uint8_t)0x03) +#define ADC_Channel_4 ((uint8_t)0x04) +#define ADC_Channel_5 ((uint8_t)0x05) +#define ADC_Channel_6 ((uint8_t)0x06) +#define ADC_Channel_7 ((uint8_t)0x07) +#define ADC_Channel_8 ((uint8_t)0x08) +#define ADC_Channel_9 ((uint8_t)0x09) +#define ADC_Channel_10 ((uint8_t)0x0A) +#define ADC_Channel_11 ((uint8_t)0x0B) +#define ADC_Channel_12 ((uint8_t)0x0C) +#define ADC_Channel_13 ((uint8_t)0x0D) +#define ADC_Channel_14 ((uint8_t)0x0E) +#define ADC_Channel_15 ((uint8_t)0x0F) +#define ADC_Channel_16 ((uint8_t)0x10) +#define ADC_Channel_17 ((uint8_t)0x11) + +#define ADC_Channel_TempSensor ((uint8_t)ADC_Channel_16) +#define ADC_Channel_Vrefint ((uint8_t)ADC_Channel_17) + +/*ADC_output_buffer*/ +#define ADC_OutputBuffer_Enable ((uint32_t)0x04000000) +#define ADC_OutputBuffer_Disable ((uint32_t)0x00000000) + +/*ADC_pga*/ +#define ADC_Pga_1 ((uint32_t)0x00000000) +#define ADC_Pga_4 ((uint32_t)0x08000000) +#define ADC_Pga_16 ((uint32_t)0x10000000) +#define ADC_Pga_64 ((uint32_t)0x18000000) + +/* ADC_sampling_time */ +#define ADC_SampleTime_1Cycles5 ((uint8_t)0x00) +#define ADC_SampleTime_7Cycles5 ((uint8_t)0x01) +#define ADC_SampleTime_13Cycles5 ((uint8_t)0x02) +#define ADC_SampleTime_28Cycles5 ((uint8_t)0x03) +#define ADC_SampleTime_41Cycles5 ((uint8_t)0x04) +#define ADC_SampleTime_55Cycles5 ((uint8_t)0x05) +#define ADC_SampleTime_71Cycles5 ((uint8_t)0x06) +#define ADC_SampleTime_239Cycles5 ((uint8_t)0x07) + +/* ADC_external_trigger_sources_for_injected_channels_conversion */ +#define ADC_ExternalTrigInjecConv_T2_TRGO ((uint32_t)0x00002000) +#define ADC_ExternalTrigInjecConv_T2_CC1 ((uint32_t)0x00003000) +#define ADC_ExternalTrigInjecConv_T3_CC4 ((uint32_t)0x00004000) +#define ADC_ExternalTrigInjecConv_T4_TRGO ((uint32_t)0x00005000) +#define ADC_ExternalTrigInjecConv_Ext_IT15_TIM8_CC4 ((uint32_t)0x00006000) + +#define ADC_ExternalTrigInjecConv_T1_TRGO ((uint32_t)0x00000000) +#define ADC_ExternalTrigInjecConv_T1_CC4 ((uint32_t)0x00001000) +#define ADC_ExternalTrigInjecConv_None ((uint32_t)0x00007000) + +#define ADC_ExternalTrigInjecConv_T4_CC3 ((uint32_t)0x00002000) +#define ADC_ExternalTrigInjecConv_T8_CC2 ((uint32_t)0x00003000) +#define ADC_ExternalTrigInjecConv_T8_CC4 ((uint32_t)0x00004000) +#define ADC_ExternalTrigInjecConv_T5_TRGO ((uint32_t)0x00005000) +#define ADC_ExternalTrigInjecConv_T5_CC4 ((uint32_t)0x00006000) + + +/* ADC_injected_channel_selection */ +#define ADC_InjectedChannel_1 ((uint8_t)0x14) +#define ADC_InjectedChannel_2 ((uint8_t)0x18) +#define ADC_InjectedChannel_3 ((uint8_t)0x1C) +#define ADC_InjectedChannel_4 ((uint8_t)0x20) + +/* ADC_analog_watchdog_selection */ +#define ADC_AnalogWatchdog_SingleRegEnable ((uint32_t)0x00800200) +#define ADC_AnalogWatchdog_SingleInjecEnable ((uint32_t)0x00400200) +#define ADC_AnalogWatchdog_SingleRegOrInjecEnable ((uint32_t)0x00C00200) +#define ADC_AnalogWatchdog_AllRegEnable ((uint32_t)0x00800000) +#define ADC_AnalogWatchdog_AllInjecEnable ((uint32_t)0x00400000) +#define ADC_AnalogWatchdog_AllRegAllInjecEnable ((uint32_t)0x00C00000) +#define ADC_AnalogWatchdog_None ((uint32_t)0x00000000) + +/* ADC_interrupts_definition */ +#define ADC_IT_EOC ((uint16_t)0x0220) +#define ADC_IT_AWD ((uint16_t)0x0140) +#define ADC_IT_JEOC ((uint16_t)0x0480) + +/* ADC_flags_definition */ +#define ADC_FLAG_AWD ((uint8_t)0x01) +#define ADC_FLAG_EOC ((uint8_t)0x02) +#define ADC_FLAG_JEOC ((uint8_t)0x04) +#define ADC_FLAG_JSTRT ((uint8_t)0x08) +#define ADC_FLAG_STRT ((uint8_t)0x10) + + +void ADC_DeInit(ADC_TypeDef* ADCx); +void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); +void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct); +void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState); +void ADC_ResetCalibration(ADC_TypeDef* ADCx); +FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx); +void ADC_StartCalibration(ADC_TypeDef* ADCx); +FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx); +void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx); +void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number); +void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx); +uint32_t ADC_GetDualModeConversionValue(void); +void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv); +void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx); +void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); +void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length); +void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset); +uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel); +void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog); +void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold); +void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel); +void ADC_TempSensorVrefintCmd(FunctionalState NewState); +FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); +void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); +ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT); +void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT); +s32 TempSensor_Volt_To_Temper(s32 Value); +void ADC_BufferCmd(ADC_TypeDef* ADCx, FunctionalState NewState); +int16_t Get_CalibrationValue(ADC_TypeDef* ADCx); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_bkp.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_bkp.h new file mode 100644 index 00000000..a429e19f --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_bkp.h @@ -0,0 +1,95 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_bkp.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* BKP firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_BKP_H +#define __CH32V30x_BKP_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* Tamper_Pin_active_level */ +#define BKP_TamperPinLevel_High ((uint16_t)0x0000) +#define BKP_TamperPinLevel_Low ((uint16_t)0x0001) + +/* RTC_output_source_to_output_on_the_Tamper_pin */ +#define BKP_RTCOutputSource_None ((uint16_t)0x0000) +#define BKP_RTCOutputSource_CalibClock ((uint16_t)0x0080) +#define BKP_RTCOutputSource_Alarm ((uint16_t)0x0100) +#define BKP_RTCOutputSource_Second ((uint16_t)0x0300) + +/* Data_Backup_Register */ +#define BKP_DR1 ((uint16_t)0x0004) +#define BKP_DR2 ((uint16_t)0x0008) +#define BKP_DR3 ((uint16_t)0x000C) +#define BKP_DR4 ((uint16_t)0x0010) +#define BKP_DR5 ((uint16_t)0x0014) +#define BKP_DR6 ((uint16_t)0x0018) +#define BKP_DR7 ((uint16_t)0x001C) +#define BKP_DR8 ((uint16_t)0x0020) +#define BKP_DR9 ((uint16_t)0x0024) +#define BKP_DR10 ((uint16_t)0x0028) +#define BKP_DR11 ((uint16_t)0x0040) +#define BKP_DR12 ((uint16_t)0x0044) +#define BKP_DR13 ((uint16_t)0x0048) +#define BKP_DR14 ((uint16_t)0x004C) +#define BKP_DR15 ((uint16_t)0x0050) +#define BKP_DR16 ((uint16_t)0x0054) +#define BKP_DR17 ((uint16_t)0x0058) +#define BKP_DR18 ((uint16_t)0x005C) +#define BKP_DR19 ((uint16_t)0x0060) +#define BKP_DR20 ((uint16_t)0x0064) +#define BKP_DR21 ((uint16_t)0x0068) +#define BKP_DR22 ((uint16_t)0x006C) +#define BKP_DR23 ((uint16_t)0x0070) +#define BKP_DR24 ((uint16_t)0x0074) +#define BKP_DR25 ((uint16_t)0x0078) +#define BKP_DR26 ((uint16_t)0x007C) +#define BKP_DR27 ((uint16_t)0x0080) +#define BKP_DR28 ((uint16_t)0x0084) +#define BKP_DR29 ((uint16_t)0x0088) +#define BKP_DR30 ((uint16_t)0x008C) +#define BKP_DR31 ((uint16_t)0x0090) +#define BKP_DR32 ((uint16_t)0x0094) +#define BKP_DR33 ((uint16_t)0x0098) +#define BKP_DR34 ((uint16_t)0x009C) +#define BKP_DR35 ((uint16_t)0x00A0) +#define BKP_DR36 ((uint16_t)0x00A4) +#define BKP_DR37 ((uint16_t)0x00A8) +#define BKP_DR38 ((uint16_t)0x00AC) +#define BKP_DR39 ((uint16_t)0x00B0) +#define BKP_DR40 ((uint16_t)0x00B4) +#define BKP_DR41 ((uint16_t)0x00B8) +#define BKP_DR42 ((uint16_t)0x00BC) + + +void BKP_DeInit(void); +void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel); +void BKP_TamperPinCmd(FunctionalState NewState); +void BKP_ITConfig(FunctionalState NewState); +void BKP_RTCOutputConfig(uint16_t BKP_RTCOutputSource); +void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue); +void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data); +uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR); +FlagStatus BKP_GetFlagStatus(void); +void BKP_ClearFlag(void); +ITStatus BKP_GetITStatus(void); +void BKP_ClearITPendingBit(void); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_can.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_can.h new file mode 100644 index 00000000..99a63bd4 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_can.h @@ -0,0 +1,364 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_can.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* CAN firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_CAN_H +#define __CH32V30x_CAN_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* CAN init structure definition */ +typedef struct +{ + uint16_t CAN_Prescaler; /* Specifies the length of a time quantum. + It ranges from 1 to 1024. */ + + uint8_t CAN_Mode; /* Specifies the CAN operating mode. + This parameter can be a value of + @ref CAN_operating_mode */ + + uint8_t CAN_SJW; /* Specifies the maximum number of time quanta + the CAN hardware is allowed to lengthen or + shorten a bit to perform resynchronization. + This parameter can be a value of + @ref CAN_synchronisation_jump_width */ + + uint8_t CAN_BS1; /* Specifies the number of time quanta in Bit + Segment 1. This parameter can be a value of + @ref CAN_time_quantum_in_bit_segment_1 */ + + uint8_t CAN_BS2; /* Specifies the number of time quanta in Bit + Segment 2. + This parameter can be a value of + @ref CAN_time_quantum_in_bit_segment_2 */ + + FunctionalState CAN_TTCM; /* Enable or disable the time triggered + communication mode. This parameter can be set + either to ENABLE or DISABLE. */ + + FunctionalState CAN_ABOM; /* Enable or disable the automatic bus-off + management. This parameter can be set either + to ENABLE or DISABLE. */ + + FunctionalState CAN_AWUM; /* Enable or disable the automatic wake-up mode. + This parameter can be set either to ENABLE or + DISABLE. */ + + FunctionalState CAN_NART; /* Enable or disable the no-automatic + retransmission mode. This parameter can be + set either to ENABLE or DISABLE. */ + + FunctionalState CAN_RFLM; /* Enable or disable the Receive FIFO Locked mode. + This parameter can be set either to ENABLE + or DISABLE. */ + + FunctionalState CAN_TXFP; /* Enable or disable the transmit FIFO priority. + This parameter can be set either to ENABLE + or DISABLE. */ +} CAN_InitTypeDef; + +/* CAN filter init structure definition */ +typedef struct +{ + uint16_t CAN_FilterIdHigh; /* Specifies the filter identification number (MSBs for a 32-bit + configuration, first one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t CAN_FilterIdLow; /* Specifies the filter identification number (LSBs for a 32-bit + configuration, second one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t CAN_FilterMaskIdHigh; /* Specifies the filter mask number or identification number, + according to the mode (MSBs for a 32-bit configuration, + first one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t CAN_FilterMaskIdLow; /* Specifies the filter mask number or identification number, + according to the mode (LSBs for a 32-bit configuration, + second one for a 16-bit configuration). + This parameter can be a value between 0x0000 and 0xFFFF */ + + uint16_t CAN_FilterFIFOAssignment; /* Specifies the FIFO (0 or 1) which will be assigned to the filter. + This parameter can be a value of @ref CAN_filter_FIFO */ + + uint8_t CAN_FilterNumber; /* Specifies the filter which will be initialized. It ranges from 0 to 13. */ + + uint8_t CAN_FilterMode; /* Specifies the filter mode to be initialized. + This parameter can be a value of @ref CAN_filter_mode */ + + uint8_t CAN_FilterScale; /* Specifies the filter scale. + This parameter can be a value of @ref CAN_filter_scale */ + + FunctionalState CAN_FilterActivation; /* Enable or disable the filter. + This parameter can be set either to ENABLE or DISABLE. */ +} CAN_FilterInitTypeDef; + +/* CAN Tx message structure definition */ +typedef struct +{ + uint32_t StdId; /* Specifies the standard identifier. + This parameter can be a value between 0 to 0x7FF. */ + + uint32_t ExtId; /* Specifies the extended identifier. + This parameter can be a value between 0 to 0x1FFFFFFF. */ + + uint8_t IDE; /* Specifies the type of identifier for the message that + will be transmitted. This parameter can be a value + of @ref CAN_identifier_type */ + + uint8_t RTR; /* Specifies the type of frame for the message that will + be transmitted. This parameter can be a value of + @ref CAN_remote_transmission_request */ + + uint8_t DLC; /* Specifies the length of the frame that will be + transmitted. This parameter can be a value between + 0 to 8 */ + + uint8_t Data[8]; /* Contains the data to be transmitted. It ranges from 0 + to 0xFF. */ +} CanTxMsg; + +/* CAN Rx message structure definition */ +typedef struct +{ + uint32_t StdId; /* Specifies the standard identifier. + This parameter can be a value between 0 to 0x7FF. */ + + uint32_t ExtId; /* Specifies the extended identifier. + This parameter can be a value between 0 to 0x1FFFFFFF. */ + + uint8_t IDE; /* Specifies the type of identifier for the message that + will be received. This parameter can be a value of + @ref CAN_identifier_type */ + + uint8_t RTR; /* Specifies the type of frame for the received message. + This parameter can be a value of + @ref CAN_remote_transmission_request */ + + uint8_t DLC; /* Specifies the length of the frame that will be received. + This parameter can be a value between 0 to 8 */ + + uint8_t Data[8]; /* Contains the data to be received. It ranges from 0 to + 0xFF. */ + + uint8_t FMI; /* Specifies the index of the filter the message stored in + the mailbox passes through. This parameter can be a + value between 0 to 0xFF */ +} CanRxMsg; + +/* CAN_sleep_constants */ +#define CAN_InitStatus_Failed ((uint8_t)0x00) /* CAN initialization failed */ +#define CAN_InitStatus_Success ((uint8_t)0x01) /* CAN initialization OK */ + +/* CAN_Mode */ +#define CAN_Mode_Normal ((uint8_t)0x00) /* normal mode */ +#define CAN_Mode_LoopBack ((uint8_t)0x01) /* loopback mode */ +#define CAN_Mode_Silent ((uint8_t)0x02) /* silent mode */ +#define CAN_Mode_Silent_LoopBack ((uint8_t)0x03) /* loopback combined with silent mode */ + +/* CAN_Operating_Mode */ +#define CAN_OperatingMode_Initialization ((uint8_t)0x00) /* Initialization mode */ +#define CAN_OperatingMode_Normal ((uint8_t)0x01) /* Normal mode */ +#define CAN_OperatingMode_Sleep ((uint8_t)0x02) /* sleep mode */ + +/* CAN_Mode_Status */ +#define CAN_ModeStatus_Failed ((uint8_t)0x00) /* CAN entering the specific mode failed */ +#define CAN_ModeStatus_Success ((uint8_t)!CAN_ModeStatus_Failed) /* CAN entering the specific mode Succeed */ + +/* CAN_synchronisation_jump_width */ +#define CAN_SJW_1tq ((uint8_t)0x00) /* 1 time quantum */ +#define CAN_SJW_2tq ((uint8_t)0x01) /* 2 time quantum */ +#define CAN_SJW_3tq ((uint8_t)0x02) /* 3 time quantum */ +#define CAN_SJW_4tq ((uint8_t)0x03) /* 4 time quantum */ + +/* CAN_time_quantum_in_bit_segment_1 */ +#define CAN_BS1_1tq ((uint8_t)0x00) /* 1 time quantum */ +#define CAN_BS1_2tq ((uint8_t)0x01) /* 2 time quantum */ +#define CAN_BS1_3tq ((uint8_t)0x02) /* 3 time quantum */ +#define CAN_BS1_4tq ((uint8_t)0x03) /* 4 time quantum */ +#define CAN_BS1_5tq ((uint8_t)0x04) /* 5 time quantum */ +#define CAN_BS1_6tq ((uint8_t)0x05) /* 6 time quantum */ +#define CAN_BS1_7tq ((uint8_t)0x06) /* 7 time quantum */ +#define CAN_BS1_8tq ((uint8_t)0x07) /* 8 time quantum */ +#define CAN_BS1_9tq ((uint8_t)0x08) /* 9 time quantum */ +#define CAN_BS1_10tq ((uint8_t)0x09) /* 10 time quantum */ +#define CAN_BS1_11tq ((uint8_t)0x0A) /* 11 time quantum */ +#define CAN_BS1_12tq ((uint8_t)0x0B) /* 12 time quantum */ +#define CAN_BS1_13tq ((uint8_t)0x0C) /* 13 time quantum */ +#define CAN_BS1_14tq ((uint8_t)0x0D) /* 14 time quantum */ +#define CAN_BS1_15tq ((uint8_t)0x0E) /* 15 time quantum */ +#define CAN_BS1_16tq ((uint8_t)0x0F) /* 16 time quantum */ + +/* CAN_time_quantum_in_bit_segment_2 */ +#define CAN_BS2_1tq ((uint8_t)0x00) /* 1 time quantum */ +#define CAN_BS2_2tq ((uint8_t)0x01) /* 2 time quantum */ +#define CAN_BS2_3tq ((uint8_t)0x02) /* 3 time quantum */ +#define CAN_BS2_4tq ((uint8_t)0x03) /* 4 time quantum */ +#define CAN_BS2_5tq ((uint8_t)0x04) /* 5 time quantum */ +#define CAN_BS2_6tq ((uint8_t)0x05) /* 6 time quantum */ +#define CAN_BS2_7tq ((uint8_t)0x06) /* 7 time quantum */ +#define CAN_BS2_8tq ((uint8_t)0x07) /* 8 time quantum */ + +/* CAN_filter_mode */ +#define CAN_FilterMode_IdMask ((uint8_t)0x00) /* identifier/mask mode */ +#define CAN_FilterMode_IdList ((uint8_t)0x01) /* identifier list mode */ + +/* CAN_filter_scale */ +#define CAN_FilterScale_16bit ((uint8_t)0x00) /* Two 16-bit filters */ +#define CAN_FilterScale_32bit ((uint8_t)0x01) /* One 32-bit filter */ + +/* CAN_filter_FIFO */ +#define CAN_Filter_FIFO0 ((uint8_t)0x00) /* Filter FIFO 0 assignment for filter x */ +#define CAN_Filter_FIFO1 ((uint8_t)0x01) /* Filter FIFO 1 assignment for filter x */ + +/* CAN_identifier_type */ +#define CAN_Id_Standard ((uint32_t)0x00000000) /* Standard Id */ +#define CAN_Id_Extended ((uint32_t)0x00000004) /* Extended Id */ + +/* CAN_remote_transmission_request */ +#define CAN_RTR_Data ((uint32_t)0x00000000) /* Data frame */ +#define CAN_RTR_Remote ((uint32_t)0x00000002) /* Remote frame */ + +/* CAN_transmit_constants */ +#define CAN_TxStatus_Failed ((uint8_t)0x00)/* CAN transmission failed */ +#define CAN_TxStatus_Ok ((uint8_t)0x01) /* CAN transmission succeeded */ +#define CAN_TxStatus_Pending ((uint8_t)0x02) /* CAN transmission pending */ +#define CAN_TxStatus_NoMailBox ((uint8_t)0x04) /* CAN cell did not provide an empty mailbox */ + +/* CAN_receive_FIFO_number_constants */ +#define CAN_FIFO0 ((uint8_t)0x00) /* CAN FIFO 0 used to receive */ +#define CAN_FIFO1 ((uint8_t)0x01) /* CAN FIFO 1 used to receive */ + +/* CAN_sleep_constants */ +#define CAN_Sleep_Failed ((uint8_t)0x00) /* CAN did not enter the sleep mode */ +#define CAN_Sleep_Ok ((uint8_t)0x01) /* CAN entered the sleep mode */ + +/* CAN_wake_up_constants */ +#define CAN_WakeUp_Failed ((uint8_t)0x00) /* CAN did not leave the sleep mode */ +#define CAN_WakeUp_Ok ((uint8_t)0x01) /* CAN leaved the sleep mode */ + +/* CAN_Error_Code_constants */ +#define CAN_ErrorCode_NoErr ((uint8_t)0x00) /* No Error */ +#define CAN_ErrorCode_StuffErr ((uint8_t)0x10) /* Stuff Error */ +#define CAN_ErrorCode_FormErr ((uint8_t)0x20) /* Form Error */ +#define CAN_ErrorCode_ACKErr ((uint8_t)0x30) /* Acknowledgment Error */ +#define CAN_ErrorCode_BitRecessiveErr ((uint8_t)0x40) /* Bit Recessive Error */ +#define CAN_ErrorCode_BitDominantErr ((uint8_t)0x50) /* Bit Dominant Error */ +#define CAN_ErrorCode_CRCErr ((uint8_t)0x60) /* CRC Error */ +#define CAN_ErrorCode_SoftwareSetErr ((uint8_t)0x70) /* Software Set Error */ + + +/* CAN_flags */ +/* Transmit Flags */ +#define CAN_FLAG_RQCP0 ((uint32_t)0x38000001) /* Request MailBox0 Flag */ +#define CAN_FLAG_RQCP1 ((uint32_t)0x38000100) /* Request MailBox1 Flag */ +#define CAN_FLAG_RQCP2 ((uint32_t)0x38010000) /* Request MailBox2 Flag */ + +/* Receive Flags */ +#define CAN_FLAG_FMP0 ((uint32_t)0x12000003) /* FIFO 0 Message Pending Flag */ +#define CAN_FLAG_FF0 ((uint32_t)0x32000008) /* FIFO 0 Full Flag */ +#define CAN_FLAG_FOV0 ((uint32_t)0x32000010) /* FIFO 0 Overrun Flag */ +#define CAN_FLAG_FMP1 ((uint32_t)0x14000003) /* FIFO 1 Message Pending Flag */ +#define CAN_FLAG_FF1 ((uint32_t)0x34000008) /* FIFO 1 Full Flag */ +#define CAN_FLAG_FOV1 ((uint32_t)0x34000010) /* FIFO 1 Overrun Flag */ + +/* Operating Mode Flags */ +#define CAN_FLAG_WKU ((uint32_t)0x31000008) /* Wake up Flag */ +#define CAN_FLAG_SLAK ((uint32_t)0x31000012) /* Sleep acknowledge Flag */ + +/* Error Flags */ +#define CAN_FLAG_EWG ((uint32_t)0x10F00001) /* Error Warning Flag */ +#define CAN_FLAG_EPV ((uint32_t)0x10F00002) /* Error Passive Flag */ +#define CAN_FLAG_BOF ((uint32_t)0x10F00004) /* Bus-Off Flag */ +#define CAN_FLAG_LEC ((uint32_t)0x30F00070) /* Last error code Flag */ + + +/* CAN_interrupts */ +#define CAN_IT_TME ((uint32_t)0x00000001) /* Transmit mailbox empty Interrupt*/ + +/* Receive Interrupts */ +#define CAN_IT_FMP0 ((uint32_t)0x00000002) /* FIFO 0 message pending Interrupt*/ +#define CAN_IT_FF0 ((uint32_t)0x00000004) /* FIFO 0 full Interrupt*/ +#define CAN_IT_FOV0 ((uint32_t)0x00000008) /* FIFO 0 overrun Interrupt*/ +#define CAN_IT_FMP1 ((uint32_t)0x00000010) /* FIFO 1 message pending Interrupt*/ +#define CAN_IT_FF1 ((uint32_t)0x00000020) /* FIFO 1 full Interrupt*/ +#define CAN_IT_FOV1 ((uint32_t)0x00000040) /* FIFO 1 overrun Interrupt*/ + +/* Operating Mode Interrupts */ +#define CAN_IT_WKU ((uint32_t)0x00010000) /* Wake-up Interrupt*/ +#define CAN_IT_SLK ((uint32_t)0x00020000) /* Sleep acknowledge Interrupt*/ + +/* Error Interrupts */ +#define CAN_IT_EWG ((uint32_t)0x00000100) /* Error warning Interrupt*/ +#define CAN_IT_EPV ((uint32_t)0x00000200) /* Error passive Interrupt*/ +#define CAN_IT_BOF ((uint32_t)0x00000400) /* Bus-off Interrupt*/ +#define CAN_IT_LEC ((uint32_t)0x00000800) /* Last error code Interrupt*/ +#define CAN_IT_ERR ((uint32_t)0x00008000) /* Error Interrupt*/ + +/* Flags named as Interrupts : kept only for FW compatibility */ +#define CAN_IT_RQCP0 CAN_IT_TME +#define CAN_IT_RQCP1 CAN_IT_TME +#define CAN_IT_RQCP2 CAN_IT_TME + +/* CAN_Legacy */ +#define CANINITFAILED CAN_InitStatus_Failed +#define CANINITOK CAN_InitStatus_Success +#define CAN_FilterFIFO0 CAN_Filter_FIFO0 +#define CAN_FilterFIFO1 CAN_Filter_FIFO1 +#define CAN_ID_STD CAN_Id_Standard +#define CAN_ID_EXT CAN_Id_Extended +#define CAN_RTR_DATA CAN_RTR_Data +#define CAN_RTR_REMOTE CAN_RTR_Remote +#define CANTXFAILE CAN_TxStatus_Failed +#define CANTXOK CAN_TxStatus_Ok +#define CANTXPENDING CAN_TxStatus_Pending +#define CAN_NO_MB CAN_TxStatus_NoMailBox +#define CANSLEEPFAILED CAN_Sleep_Failed +#define CANSLEEPOK CAN_Sleep_Ok +#define CANWAKEUPFAILED CAN_WakeUp_Failed +#define CANWAKEUPOK CAN_WakeUp_Ok + + +void CAN_DeInit(CAN_TypeDef* CANx); +uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct); +void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct); +void CAN_StructInit(CAN_InitTypeDef* CAN_InitStruct); +void CAN_SlaveStartBank(uint8_t CAN_BankNumber); +void CAN_DBGFreeze(CAN_TypeDef* CANx, FunctionalState NewState); +void CAN_TTComModeCmd(CAN_TypeDef* CANx, FunctionalState NewState); +uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage); +uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox); +void CAN_CancelTransmit(CAN_TypeDef* CANx, uint8_t Mailbox); +void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage); +void CAN_FIFORelease(CAN_TypeDef* CANx, uint8_t FIFONumber); +uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber); +uint8_t CAN_OperatingModeRequest(CAN_TypeDef* CANx, uint8_t CAN_OperatingMode); +uint8_t CAN_Sleep(CAN_TypeDef* CANx); +uint8_t CAN_WakeUp(CAN_TypeDef* CANx); +uint8_t CAN_GetLastErrorCode(CAN_TypeDef* CANx); +uint8_t CAN_GetReceiveErrorCounter(CAN_TypeDef* CANx); +uint8_t CAN_GetLSBTransmitErrorCounter(CAN_TypeDef* CANx); +void CAN_ITConfig(CAN_TypeDef* CANx, uint32_t CAN_IT, FunctionalState NewState); +FlagStatus CAN_GetFlagStatus(CAN_TypeDef* CANx, uint32_t CAN_FLAG); +void CAN_ClearFlag(CAN_TypeDef* CANx, uint32_t CAN_FLAG); +ITStatus CAN_GetITStatus(CAN_TypeDef* CANx, uint32_t CAN_IT); +void CAN_ClearITPendingBit(CAN_TypeDef* CANx, uint32_t CAN_IT); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_crc.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_crc.h new file mode 100644 index 00000000..2e1ce329 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_crc.h @@ -0,0 +1,35 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_crc.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* CRC firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_CRC_H +#define __CH32V30x_CRC_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + + +void CRC_ResetDR(void); +uint32_t CRC_CalcCRC(uint32_t Data); +uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength); +uint32_t CRC_GetCRC(void); +void CRC_SetIDRegister(uint8_t IDValue); +uint8_t CRC_GetIDRegister(void); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dac.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dac.h new file mode 100644 index 00000000..63ec23a9 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dac.h @@ -0,0 +1,122 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_dac.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* DAC firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_DAC_H +#define __CH32V30x_DAC_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* DAC Init structure definition */ +typedef struct +{ + uint32_t DAC_Trigger; /* Specifies the external trigger for the selected DAC channel. + This parameter can be a value of @ref DAC_trigger_selection */ + + uint32_t DAC_WaveGeneration; /* Specifies whether DAC channel noise waves or triangle waves + are generated, or whether no wave is generated. + This parameter can be a value of @ref DAC_wave_generation */ + + uint32_t DAC_LFSRUnmask_TriangleAmplitude; /* Specifies the LFSR mask for noise wave generation or + the maximum amplitude triangle generation for the DAC channel. + This parameter can be a value of @ref DAC_lfsrunmask_triangleamplitude */ + + uint32_t DAC_OutputBuffer; /* Specifies whether the DAC channel output buffer is enabled or disabled. + This parameter can be a value of @ref DAC_output_buffer */ +}DAC_InitTypeDef; + + +/* DAC_trigger_selection */ +#define DAC_Trigger_None ((uint32_t)0x00000000) /* Conversion is automatic once the DAC1_DHRxxxx register + has been loaded, and not by external trigger */ +#define DAC_Trigger_T6_TRGO ((uint32_t)0x00000004) /* TIM6 TRGO selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_T8_TRGO ((uint32_t)0x0000000C) /* TIM8 TRGO selected as external conversion trigger for DAC channel + only in High-density devices*/ +#define DAC_Trigger_T3_TRGO ((uint32_t)0x0000000C) /* TIM8 TRGO selected as external conversion trigger for DAC channel + only in Connectivity line, Medium-density and Low-density Value Line devices */ +#define DAC_Trigger_T7_TRGO ((uint32_t)0x00000014) /* TIM7 TRGO selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_T5_TRGO ((uint32_t)0x0000001C) /* TIM5 TRGO selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_T15_TRGO ((uint32_t)0x0000001C) /* TIM15 TRGO selected as external conversion trigger for DAC channel + only in Medium-density and Low-density Value Line devices*/ +#define DAC_Trigger_T2_TRGO ((uint32_t)0x00000024) /* TIM2 TRGO selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_T4_TRGO ((uint32_t)0x0000002C) /* TIM4 TRGO selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_Ext_IT9 ((uint32_t)0x00000034) /* EXTI Line9 event selected as external conversion trigger for DAC channel */ +#define DAC_Trigger_Software ((uint32_t)0x0000003C) /* Conversion started by software trigger for DAC channel */ + +/* DAC_wave_generation */ +#define DAC_WaveGeneration_None ((uint32_t)0x00000000) +#define DAC_WaveGeneration_Noise ((uint32_t)0x00000040) +#define DAC_WaveGeneration_Triangle ((uint32_t)0x00000080) + + +/* DAC_lfsrunmask_triangleamplitude */ +#define DAC_LFSRUnmask_Bit0 ((uint32_t)0x00000000) /* Unmask DAC channel LFSR bit0 for noise wave generation */ +#define DAC_LFSRUnmask_Bits1_0 ((uint32_t)0x00000100) /* Unmask DAC channel LFSR bit[1:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits2_0 ((uint32_t)0x00000200) /* Unmask DAC channel LFSR bit[2:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits3_0 ((uint32_t)0x00000300) /* Unmask DAC channel LFSR bit[3:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits4_0 ((uint32_t)0x00000400) /* Unmask DAC channel LFSR bit[4:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits5_0 ((uint32_t)0x00000500) /* Unmask DAC channel LFSR bit[5:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits6_0 ((uint32_t)0x00000600) /* Unmask DAC channel LFSR bit[6:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits7_0 ((uint32_t)0x00000700) /* Unmask DAC channel LFSR bit[7:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits8_0 ((uint32_t)0x00000800) /* Unmask DAC channel LFSR bit[8:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits9_0 ((uint32_t)0x00000900) /* Unmask DAC channel LFSR bit[9:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits10_0 ((uint32_t)0x00000A00) /* Unmask DAC channel LFSR bit[10:0] for noise wave generation */ +#define DAC_LFSRUnmask_Bits11_0 ((uint32_t)0x00000B00) /* Unmask DAC channel LFSR bit[11:0] for noise wave generation */ +#define DAC_TriangleAmplitude_1 ((uint32_t)0x00000000) /* Select max triangle amplitude of 1 */ +#define DAC_TriangleAmplitude_3 ((uint32_t)0x00000100) /* Select max triangle amplitude of 3 */ +#define DAC_TriangleAmplitude_7 ((uint32_t)0x00000200) /* Select max triangle amplitude of 7 */ +#define DAC_TriangleAmplitude_15 ((uint32_t)0x00000300) /* Select max triangle amplitude of 15 */ +#define DAC_TriangleAmplitude_31 ((uint32_t)0x00000400) /* Select max triangle amplitude of 31 */ +#define DAC_TriangleAmplitude_63 ((uint32_t)0x00000500) /* Select max triangle amplitude of 63 */ +#define DAC_TriangleAmplitude_127 ((uint32_t)0x00000600) /* Select max triangle amplitude of 127 */ +#define DAC_TriangleAmplitude_255 ((uint32_t)0x00000700) /* Select max triangle amplitude of 255 */ +#define DAC_TriangleAmplitude_511 ((uint32_t)0x00000800) /* Select max triangle amplitude of 511 */ +#define DAC_TriangleAmplitude_1023 ((uint32_t)0x00000900) /* Select max triangle amplitude of 1023 */ +#define DAC_TriangleAmplitude_2047 ((uint32_t)0x00000A00) /* Select max triangle amplitude of 2047 */ +#define DAC_TriangleAmplitude_4095 ((uint32_t)0x00000B00) /* Select max triangle amplitude of 4095 */ + +/* DAC_output_buffer */ +#define DAC_OutputBuffer_Enable ((uint32_t)0x00000000) +#define DAC_OutputBuffer_Disable ((uint32_t)0x00000002) + +/* DAC_Channel_selection */ +#define DAC_Channel_1 ((uint32_t)0x00000000) +#define DAC_Channel_2 ((uint32_t)0x00000010) + +/* DAC_data_alignment */ +#define DAC_Align_12b_R ((uint32_t)0x00000000) +#define DAC_Align_12b_L ((uint32_t)0x00000004) +#define DAC_Align_8b_R ((uint32_t)0x00000008) + +/* DAC_wave_generation */ +#define DAC_Wave_Noise ((uint32_t)0x00000040) +#define DAC_Wave_Triangle ((uint32_t)0x00000080) + + +void DAC_DeInit(void); +void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct); +void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct); +void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState); +void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState); +void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState); +void DAC_DualSoftwareTriggerCmd(FunctionalState NewState); +void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState); +void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data); +void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data); +void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1); +uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dbgmcu.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dbgmcu.h new file mode 100644 index 00000000..aa5763ba --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dbgmcu.h @@ -0,0 +1,48 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_dbgmcu.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* DBGMCU firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_DBGMCU_H +#define __CH32V30x_DBGMCU_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + + +/* CFGR0 Register */ +#define DBGMCU_IWDG_STOP ((uint32_t)0x00000001) +#define DBGMCU_WWDG_STOP ((uint32_t)0x00000002) +#define DBGMCU_I2C1_SMBUS_TIMEOUT ((uint32_t)0x00000004) +#define DBGMCU_I2C2_SMBUS_TIMEOUT ((uint32_t)0x00000008) +#define DBGMCU_TIM1_STOP ((uint32_t)0x00000010) +#define DBGMCU_TIM2_STOP ((uint32_t)0x00000020) +#define DBGMCU_TIM3_STOP ((uint32_t)0x00000040) +#define DBGMCU_TIM4_STOP ((uint32_t)0x00000080) + +/* CFGR1 Register */ +#define DBGMCU_SLEEP ((uint32_t)0x00000001) +#define DBGMCU_STOP ((uint32_t)0x00000002) +#define DBGMCU_STANDBY ((uint32_t)0x00000004) + + +void DBGMCU_Config(uint32_t DBGMCU_Periph, FunctionalState NewState); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dma.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dma.h new file mode 100644 index 00000000..305c7f6c --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dma.h @@ -0,0 +1,266 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_dma.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* DMA firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_DMA_H +#define __CH32V30x_DMA_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* DMA Init structure definition */ +typedef struct +{ + uint32_t DMA_PeripheralBaseAddr; /* Specifies the peripheral base address for DMAy Channelx. */ + + uint32_t DMA_MemoryBaseAddr; /* Specifies the memory base address for DMAy Channelx. */ + + uint32_t DMA_DIR; /* Specifies if the peripheral is the source or destination. + This parameter can be a value of @ref DMA_data_transfer_direction */ + + uint32_t DMA_BufferSize; /* Specifies the buffer size, in data unit, of the specified Channel. + The data unit is equal to the configuration set in DMA_PeripheralDataSize + or DMA_MemoryDataSize members depending in the transfer direction. */ + + uint32_t DMA_PeripheralInc; /* Specifies whether the Peripheral address register is incremented or not. + This parameter can be a value of @ref DMA_peripheral_incremented_mode */ + + uint32_t DMA_MemoryInc; /* Specifies whether the memory address register is incremented or not. + This parameter can be a value of @ref DMA_memory_incremented_mode */ + + uint32_t DMA_PeripheralDataSize; /* Specifies the Peripheral data width. + This parameter can be a value of @ref DMA_peripheral_data_size */ + + uint32_t DMA_MemoryDataSize; /* Specifies the Memory data width. + This parameter can be a value of @ref DMA_memory_data_size */ + + uint32_t DMA_Mode; /* Specifies the operation mode of the DMAy Channelx. + This parameter can be a value of @ref DMA_circular_normal_mode. + @note: The circular buffer mode cannot be used if the memory-to-memory + data transfer is configured on the selected Channel */ + + uint32_t DMA_Priority; /* Specifies the software priority for the DMAy Channelx. + This parameter can be a value of @ref DMA_priority_level */ + + uint32_t DMA_M2M; /* Specifies if the DMAy Channelx will be used in memory-to-memory transfer. + This parameter can be a value of @ref DMA_memory_to_memory */ +}DMA_InitTypeDef; + +/* DMA_data_transfer_direction */ +#define DMA_DIR_PeripheralDST ((uint32_t)0x00000010) +#define DMA_DIR_PeripheralSRC ((uint32_t)0x00000000) + +/* DMA_peripheral_incremented_mode */ +#define DMA_PeripheralInc_Enable ((uint32_t)0x00000040) +#define DMA_PeripheralInc_Disable ((uint32_t)0x00000000) + +/* DMA_memory_incremented_mode */ +#define DMA_MemoryInc_Enable ((uint32_t)0x00000080) +#define DMA_MemoryInc_Disable ((uint32_t)0x00000000) + +/* DMA_peripheral_data_size */ +#define DMA_PeripheralDataSize_Byte ((uint32_t)0x00000000) +#define DMA_PeripheralDataSize_HalfWord ((uint32_t)0x00000100) +#define DMA_PeripheralDataSize_Word ((uint32_t)0x00000200) + +/* DMA_memory_data_size */ +#define DMA_MemoryDataSize_Byte ((uint32_t)0x00000000) +#define DMA_MemoryDataSize_HalfWord ((uint32_t)0x00000400) +#define DMA_MemoryDataSize_Word ((uint32_t)0x00000800) + +/* DMA_circular_normal_mode */ +#define DMA_Mode_Circular ((uint32_t)0x00000020) +#define DMA_Mode_Normal ((uint32_t)0x00000000) + +/* DMA_priority_level */ +#define DMA_Priority_VeryHigh ((uint32_t)0x00003000) +#define DMA_Priority_High ((uint32_t)0x00002000) +#define DMA_Priority_Medium ((uint32_t)0x00001000) +#define DMA_Priority_Low ((uint32_t)0x00000000) + +/* DMA_memory_to_memory */ +#define DMA_M2M_Enable ((uint32_t)0x00004000) +#define DMA_M2M_Disable ((uint32_t)0x00000000) + +/* DMA_interrupts_definition */ +#define DMA_IT_TC ((uint32_t)0x00000002) +#define DMA_IT_HT ((uint32_t)0x00000004) +#define DMA_IT_TE ((uint32_t)0x00000008) + +#define DMA1_IT_GL1 ((uint32_t)0x00000001) +#define DMA1_IT_TC1 ((uint32_t)0x00000002) +#define DMA1_IT_HT1 ((uint32_t)0x00000004) +#define DMA1_IT_TE1 ((uint32_t)0x00000008) +#define DMA1_IT_GL2 ((uint32_t)0x00000010) +#define DMA1_IT_TC2 ((uint32_t)0x00000020) +#define DMA1_IT_HT2 ((uint32_t)0x00000040) +#define DMA1_IT_TE2 ((uint32_t)0x00000080) +#define DMA1_IT_GL3 ((uint32_t)0x00000100) +#define DMA1_IT_TC3 ((uint32_t)0x00000200) +#define DMA1_IT_HT3 ((uint32_t)0x00000400) +#define DMA1_IT_TE3 ((uint32_t)0x00000800) +#define DMA1_IT_GL4 ((uint32_t)0x00001000) +#define DMA1_IT_TC4 ((uint32_t)0x00002000) +#define DMA1_IT_HT4 ((uint32_t)0x00004000) +#define DMA1_IT_TE4 ((uint32_t)0x00008000) +#define DMA1_IT_GL5 ((uint32_t)0x00010000) +#define DMA1_IT_TC5 ((uint32_t)0x00020000) +#define DMA1_IT_HT5 ((uint32_t)0x00040000) +#define DMA1_IT_TE5 ((uint32_t)0x00080000) +#define DMA1_IT_GL6 ((uint32_t)0x00100000) +#define DMA1_IT_TC6 ((uint32_t)0x00200000) +#define DMA1_IT_HT6 ((uint32_t)0x00400000) +#define DMA1_IT_TE6 ((uint32_t)0x00800000) +#define DMA1_IT_GL7 ((uint32_t)0x01000000) +#define DMA1_IT_TC7 ((uint32_t)0x02000000) +#define DMA1_IT_HT7 ((uint32_t)0x04000000) +#define DMA1_IT_TE7 ((uint32_t)0x08000000) + +#define DMA2_IT_GL1 ((uint32_t)0x10000001) +#define DMA2_IT_TC1 ((uint32_t)0x10000002) +#define DMA2_IT_HT1 ((uint32_t)0x10000004) +#define DMA2_IT_TE1 ((uint32_t)0x10000008) +#define DMA2_IT_GL2 ((uint32_t)0x10000010) +#define DMA2_IT_TC2 ((uint32_t)0x10000020) +#define DMA2_IT_HT2 ((uint32_t)0x10000040) +#define DMA2_IT_TE2 ((uint32_t)0x10000080) +#define DMA2_IT_GL3 ((uint32_t)0x10000100) +#define DMA2_IT_TC3 ((uint32_t)0x10000200) +#define DMA2_IT_HT3 ((uint32_t)0x10000400) +#define DMA2_IT_TE3 ((uint32_t)0x10000800) +#define DMA2_IT_GL4 ((uint32_t)0x10001000) +#define DMA2_IT_TC4 ((uint32_t)0x10002000) +#define DMA2_IT_HT4 ((uint32_t)0x10004000) +#define DMA2_IT_TE4 ((uint32_t)0x10008000) +#define DMA2_IT_GL5 ((uint32_t)0x10010000) +#define DMA2_IT_TC5 ((uint32_t)0x10020000) +#define DMA2_IT_HT5 ((uint32_t)0x10040000) +#define DMA2_IT_TE5 ((uint32_t)0x10080000) +#define DMA2_IT_GL6 ((uint32_t)0x10100000) +#define DMA2_IT_TC6 ((uint32_t)0x10200000) +#define DMA2_IT_HT6 ((uint32_t)0x10400000) +#define DMA2_IT_TE6 ((uint32_t)0x10800000) +#define DMA2_IT_GL7 ((uint32_t)0x11000000) +#define DMA2_IT_TC7 ((uint32_t)0x12000000) +#define DMA2_IT_HT7 ((uint32_t)0x14000000) +#define DMA2_IT_TE7 ((uint32_t)0x18000000) + +#define DMA2_IT_GL8 ((uint32_t)0x20000001) +#define DMA2_IT_TC8 ((uint32_t)0x20000002) +#define DMA2_IT_HT8 ((uint32_t)0x20000004) +#define DMA2_IT_TE8 ((uint32_t)0x20000008) +#define DMA2_IT_GL9 ((uint32_t)0x20000010) +#define DMA2_IT_TC9 ((uint32_t)0x20000020) +#define DMA2_IT_HT9 ((uint32_t)0x20000040) +#define DMA2_IT_TE9 ((uint32_t)0x20000080) +#define DMA2_IT_GL10 ((uint32_t)0x20000100) +#define DMA2_IT_TC10 ((uint32_t)0x20000200) +#define DMA2_IT_HT10 ((uint32_t)0x20000400) +#define DMA2_IT_TE10 ((uint32_t)0x20000800) +#define DMA2_IT_GL11 ((uint32_t)0x20001000) +#define DMA2_IT_TC11 ((uint32_t)0x20002000) +#define DMA2_IT_HT11 ((uint32_t)0x20004000) +#define DMA2_IT_TE11 ((uint32_t)0x20008000) + +/* DMA_flags_definition */ +#define DMA1_FLAG_GL1 ((uint32_t)0x00000001) +#define DMA1_FLAG_TC1 ((uint32_t)0x00000002) +#define DMA1_FLAG_HT1 ((uint32_t)0x00000004) +#define DMA1_FLAG_TE1 ((uint32_t)0x00000008) +#define DMA1_FLAG_GL2 ((uint32_t)0x00000010) +#define DMA1_FLAG_TC2 ((uint32_t)0x00000020) +#define DMA1_FLAG_HT2 ((uint32_t)0x00000040) +#define DMA1_FLAG_TE2 ((uint32_t)0x00000080) +#define DMA1_FLAG_GL3 ((uint32_t)0x00000100) +#define DMA1_FLAG_TC3 ((uint32_t)0x00000200) +#define DMA1_FLAG_HT3 ((uint32_t)0x00000400) +#define DMA1_FLAG_TE3 ((uint32_t)0x00000800) +#define DMA1_FLAG_GL4 ((uint32_t)0x00001000) +#define DMA1_FLAG_TC4 ((uint32_t)0x00002000) +#define DMA1_FLAG_HT4 ((uint32_t)0x00004000) +#define DMA1_FLAG_TE4 ((uint32_t)0x00008000) +#define DMA1_FLAG_GL5 ((uint32_t)0x00010000) +#define DMA1_FLAG_TC5 ((uint32_t)0x00020000) +#define DMA1_FLAG_HT5 ((uint32_t)0x00040000) +#define DMA1_FLAG_TE5 ((uint32_t)0x00080000) +#define DMA1_FLAG_GL6 ((uint32_t)0x00100000) +#define DMA1_FLAG_TC6 ((uint32_t)0x00200000) +#define DMA1_FLAG_HT6 ((uint32_t)0x00400000) +#define DMA1_FLAG_TE6 ((uint32_t)0x00800000) +#define DMA1_FLAG_GL7 ((uint32_t)0x01000000) +#define DMA1_FLAG_TC7 ((uint32_t)0x02000000) +#define DMA1_FLAG_HT7 ((uint32_t)0x04000000) +#define DMA1_FLAG_TE7 ((uint32_t)0x08000000) + +#define DMA2_FLAG_GL1 ((uint32_t)0x10000001) +#define DMA2_FLAG_TC1 ((uint32_t)0x10000002) +#define DMA2_FLAG_HT1 ((uint32_t)0x10000004) +#define DMA2_FLAG_TE1 ((uint32_t)0x10000008) +#define DMA2_FLAG_GL2 ((uint32_t)0x10000010) +#define DMA2_FLAG_TC2 ((uint32_t)0x10000020) +#define DMA2_FLAG_HT2 ((uint32_t)0x10000040) +#define DMA2_FLAG_TE2 ((uint32_t)0x10000080) +#define DMA2_FLAG_GL3 ((uint32_t)0x10000100) +#define DMA2_FLAG_TC3 ((uint32_t)0x10000200) +#define DMA2_FLAG_HT3 ((uint32_t)0x10000400) +#define DMA2_FLAG_TE3 ((uint32_t)0x10000800) +#define DMA2_FLAG_GL4 ((uint32_t)0x10001000) +#define DMA2_FLAG_TC4 ((uint32_t)0x10002000) +#define DMA2_FLAG_HT4 ((uint32_t)0x10004000) +#define DMA2_FLAG_TE4 ((uint32_t)0x10008000) +#define DMA2_FLAG_GL5 ((uint32_t)0x10010000) +#define DMA2_FLAG_TC5 ((uint32_t)0x10020000) +#define DMA2_FLAG_HT5 ((uint32_t)0x10040000) +#define DMA2_FLAG_TE5 ((uint32_t)0x10080000) +#define DMA2_FLAG_GL6 ((uint32_t)0x10100000) +#define DMA2_FLAG_TC6 ((uint32_t)0x10200000) +#define DMA2_FLAG_HT6 ((uint32_t)0x10400000) +#define DMA2_FLAG_TE6 ((uint32_t)0x10800000) +#define DMA2_FLAG_GL7 ((uint32_t)0x11000000) +#define DMA2_FLAG_TC7 ((uint32_t)0x12000000) +#define DMA2_FLAG_HT7 ((uint32_t)0x14000000) +#define DMA2_FLAG_TE7 ((uint32_t)0x18000000) + +#define DMA2_FLAG_GL8 ((uint32_t)0x20000001) +#define DMA2_FLAG_TC8 ((uint32_t)0x20000002) +#define DMA2_FLAG_HT8 ((uint32_t)0x20000004) +#define DMA2_FLAG_TE8 ((uint32_t)0x20000008) +#define DMA2_FLAG_GL9 ((uint32_t)0x20000010) +#define DMA2_FLAG_TC9 ((uint32_t)0x20000020) +#define DMA2_FLAG_HT9 ((uint32_t)0x20000040) +#define DMA2_FLAG_TE9 ((uint32_t)0x20000080) +#define DMA2_FLAG_GL10 ((uint32_t)0x20000100) +#define DMA2_FLAG_TC10 ((uint32_t)0x20000200) +#define DMA2_FLAG_HT10 ((uint32_t)0x20000400) +#define DMA2_FLAG_TE10 ((uint32_t)0x20000800) +#define DMA2_FLAG_GL11 ((uint32_t)0x20001000) +#define DMA2_FLAG_TC11 ((uint32_t)0x20002000) +#define DMA2_FLAG_HT11 ((uint32_t)0x20004000) +#define DMA2_FLAG_TE11 ((uint32_t)0x20008000) + + +void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx); +void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct); +void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct); +void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState); +void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState); +void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); +uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx); +FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG); +void DMA_ClearFlag(uint32_t DMAy_FLAG); +ITStatus DMA_GetITStatus(uint32_t DMAy_IT); +void DMA_ClearITPendingBit(uint32_t DMAy_IT); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dvp.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dvp.h new file mode 100644 index 00000000..d23b7378 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_dvp.h @@ -0,0 +1,65 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_dvp.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* DVP firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_DVP_H +#define __CH32V30x_DVP_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + + /* DVP Data Mode */ + typedef enum + { + Video_Mode = 0, + JPEG_Mode, + }DVP_Data_ModeTypeDef; + + + /* DVP DMA */ + typedef enum + { + DVP_DMA_Disable = 0, + DVP_DMA_Enable, + }DVP_DMATypeDef; + + /* DVP FLAG and FIFO Reset */ + typedef enum + { + DVP_FLAG_FIFO_RESET_Disable = 0, + DVP_FLAG_FIFO_RESET_Enable, + }DVP_FLAG_FIFO_RESETTypeDef; + + /* DVP RX Reset */ + typedef enum + { + DVP_RX_RESET_Disable = 0, + DVP_RX_RESET_Enable, + }DVP_RX_RESETTypeDef; + + + + void DVP_INTCfg( uint8_t s, uint8_t i ); + void DVP_Mode( uint8_t s, DVP_Data_ModeTypeDef i); + void DVP_Cfg( DVP_DMATypeDef s, DVP_FLAG_FIFO_RESETTypeDef i, DVP_RX_RESETTypeDef j); + + + +#ifdef __cplusplus +} +#endif + +#endif + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_eth.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_eth.h new file mode 100644 index 00000000..9221858a --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_eth.h @@ -0,0 +1,1323 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_eth.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* ETH firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_ETH_H +#define __CH32V30x_ETH_H + +#include "ch32v30x.h" + + +#define PHY_10BASE_T_LINKED 1 +#define PHY_10BASE_T_NOT_LINKED 0 + +#define DMA_TPS_Mask ((uint32_t)0x00700000) +#define DMA_RPS_Mask ((uint32_t)0x000E0000) + +/* ETH Init structure definition */ +typedef struct { + uint32_t ETH_AutoNegotiation; /* Selects or not the AutoNegotiation mode for the external PHY + The AutoNegotiation allows an automatic setting of the Speed (10/100Mbps) + and the mode (half/full-duplex). + This parameter can be a value of @ref ETH_AutoNegotiation */ + + uint32_t ETH_Watchdog; /* Selects or not the Watchdog timer + When enabled, the MAC allows no more then 2048 bytes to be received. + When disabled, the MAC can receive up to 16384 bytes. + This parameter can be a value of @ref ETH_watchdog */ + + uint32_t ETH_Jabber; /* Selects or not Jabber timer + When enabled, the MAC allows no more then 2048 bytes to be sent. + When disabled, the MAC can send up to 16384 bytes. + This parameter can be a value of @ref ETH_Jabber */ + + uint32_t ETH_InterFrameGap; /* Selects the minimum IFG between frames during transmission + This parameter can be a value of @ref ETH_Inter_Frame_Gap */ + + uint32_t ETH_CarrierSense; /* Selects or not the Carrier Sense + This parameter can be a value of @ref ETH_Carrier_Sense */ + + uint32_t ETH_Speed; /* Sets the Ethernet speed: 10/100 Mbps + This parameter can be a value of @ref ETH_Speed */ + + uint32_t ETH_ReceiveOwn; /* Selects or not the ReceiveOwn + ReceiveOwn allows the reception of frames when the TX_EN signal is asserted + in Half-Duplex mode + This parameter can be a value of @ref ETH_Receive_Own */ + + uint32_t ETH_LoopbackMode; /* Selects or not the internal MAC MII Loopback mode + This parameter can be a value of @ref ETH_Loop_Back_Mode */ + + uint32_t ETH_Mode; /* Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode + This parameter can be a value of @ref ETH_Duplex_Mode */ + + uint32_t ETH_ChecksumOffload; /* Selects or not the IPv4 checksum checking for received frame payloads' TCP/UDP/ICMP headers. + This parameter can be a value of @ref ETH_Checksum_Offload */ + + uint32_t ETH_RetryTransmission; /* Selects or not the MAC attempt retries transmission, based on the settings of BL, + when a colision occurs (Half-Duplex mode) + This parameter can be a value of @ref ETH_Retry_Transmission */ + + uint32_t ETH_AutomaticPadCRCStrip; /* Selects or not the Automatic MAC Pad/CRC Stripping + This parameter can be a value of @ref ETH_Automatic_Pad_CRC_Strip */ + + uint32_t ETH_BackOffLimit; /* Selects the BackOff limit value + This parameter can be a value of @ref ETH_Back_Off_Limit */ + + uint32_t ETH_DeferralCheck; /* Selects or not the deferral check function (Half-Duplex mode) + This parameter can be a value of @ref ETH_Deferral_Check */ + + uint32_t ETH_ReceiveAll; /* Selects or not all frames reception by the MAC (No fitering) + This parameter can be a value of @ref ETH_Receive_All */ + + uint32_t ETH_SourceAddrFilter; /* Selects the Source Address Filter mode + This parameter can be a value of @ref ETH_Source_Addr_Filter */ + + uint32_t ETH_PassControlFrames; /* Sets the forwarding mode of the control frames (including unicast and multicast PAUSE frames) + This parameter can be a value of @ref ETH_Pass_Control_Frames */ + + uint32_t ETH_BroadcastFramesReception; /* Selects or not the reception of Broadcast Frames + This parameter can be a value of @ref ETH_Broadcast_Frames_Reception */ + + uint32_t ETH_DestinationAddrFilter; /* Sets the destination filter mode for both unicast and multicast frames + This parameter can be a value of @ref ETH_Destination_Addr_Filter */ + + uint32_t ETH_PromiscuousMode; /* Selects or not the Promiscuous Mode + This parameter can be a value of @ref ETH_Promiscuous_Mode */ + + uint32_t ETH_MulticastFramesFilter; /* Selects the Multicast Frames filter mode: None/HashTableFilter/PerfectFilter/PerfectHashTableFilter + This parameter can be a value of @ref ETH_Multicast_Frames_Filter */ + + uint32_t ETH_UnicastFramesFilter; /* Selects the Unicast Frames filter mode: HashTableFilter/PerfectFilter/PerfectHashTableFilter + This parameter can be a value of @ref ETH_Unicast_Frames_Filter */ + + uint32_t ETH_HashTableHigh; /* This field holds the higher 32 bits of Hash table. */ + + uint32_t ETH_HashTableLow; /* This field holds the lower 32 bits of Hash table. */ + + uint32_t ETH_PauseTime; /* This field holds the value to be used in the Pause Time field in the + transmit control frame */ + + uint32_t ETH_ZeroQuantaPause; /* Selects or not the automatic generation of Zero-Quanta Pause Control frames + This parameter can be a value of @ref ETH_Zero_Quanta_Pause */ + + uint32_t ETH_PauseLowThreshold; /* This field configures the threshold of the PAUSE to be checked for + automatic retransmission of PAUSE Frame + This parameter can be a value of @ref ETH_Pause_Low_Threshold */ + + uint32_t ETH_UnicastPauseFrameDetect; /* Selects or not the MAC detection of the Pause frames (with MAC Address0 + unicast address and unique multicast address) + This parameter can be a value of @ref ETH_Unicast_Pause_Frame_Detect */ + + uint32_t ETH_ReceiveFlowControl; /* Enables or disables the MAC to decode the received Pause frame and + disable its transmitter for a specified time (Pause Time) + This parameter can be a value of @ref ETH_Receive_Flow_Control */ + + uint32_t ETH_TransmitFlowControl; /* Enables or disables the MAC to transmit Pause frames (Full-Duplex mode) + or the MAC back-pressure operation (Half-Duplex mode) + This parameter can be a value of @ref ETH_Transmit_Flow_Control */ + + uint32_t ETH_VLANTagComparison; /* Selects the 12-bit VLAN identifier or the complete 16-bit VLAN tag for + comparison and filtering + This parameter can be a value of @ref ETH_VLAN_Tag_Comparison */ + + uint32_t ETH_VLANTagIdentifier; /* Holds the VLAN tag identifier for receive frames */ + + uint32_t ETH_DropTCPIPChecksumErrorFrame; /* Selects or not the Dropping of TCP/IP Checksum Error Frames + This parameter can be a value of @ref ETH_Drop_TCP_IP_Checksum_Error_Frame */ + + uint32_t ETH_ReceiveStoreForward; /* Enables or disables the Receive store and forward mode + This parameter can be a value of @ref ETH_Receive_Store_Forward */ + + uint32_t ETH_FlushReceivedFrame; /* Enables or disables the flushing of received frames + This parameter can be a value of @ref ETH_Flush_Received_Frame */ + + uint32_t ETH_TransmitStoreForward; /* Enables or disables Transmit store and forward mode + This parameter can be a value of @ref ETH_Transmit_Store_Forward */ + + uint32_t ETH_TransmitThresholdControl; /* Selects or not the Transmit Threshold Control + This parameter can be a value of @ref ETH_Transmit_Threshold_Control */ + + uint32_t ETH_ForwardErrorFrames; /* Selects or not the forward to the DMA of erroneous frames + This parameter can be a value of @ref ETH_Forward_Error_Frames */ + + uint32_t ETH_ForwardUndersizedGoodFrames; /* Enables or disables the Rx FIFO to forward Undersized frames (frames with no Error + and length less than 64 bytes) including pad-bytes and CRC) + This parameter can be a value of @ref ETH_Forward_Undersized_Good_Frames */ + + uint32_t ETH_ReceiveThresholdControl; /* Selects the threshold level of the Receive FIFO + This parameter can be a value of @ref ETH_Receive_Threshold_Control */ + + uint32_t ETH_SecondFrameOperate; /* Selects or not the Operate on second frame mode, which allows the DMA to process a second + frame of Transmit data even before obtaining the status for the first frame. + This parameter can be a value of @ref ETH_Second_Frame_Operate */ + + uint32_t ETH_AddressAlignedBeats; /* Enables or disables the Address Aligned Beats + This parameter can be a value of @ref ETH_Address_Aligned_Beats */ + + uint32_t ETH_FixedBurst; /* Enables or disables the AHB Master interface fixed burst transfers + This parameter can be a value of @ref ETH_Fixed_Burst */ + + uint32_t ETH_RxDMABurstLength; /* Indicates the maximum number of beats to be transferred in one Rx DMA transaction + This parameter can be a value of @ref ETH_Rx_DMA_Burst_Length */ + + uint32_t ETH_TxDMABurstLength; /* Indicates sthe maximum number of beats to be transferred in one Tx DMA transaction + This parameter can be a value of @ref ETH_Tx_DMA_Burst_Length */ + + uint32_t ETH_DescriptorSkipLength; /* Specifies the number of word to skip between two unchained descriptors (Ring mode) */ + + uint32_t ETH_DMAArbitration; /* Selects the DMA Tx/Rx arbitration + This parameter can be a value of @ref ETH_DMA_Arbitration */ +}ETH_InitTypeDef; + + + +/* ETH delay.Just for Ethernet */ +#define _eth_delay_ ETH_Delay /* Default _eth_delay_ function with less precise timing */ + +/* definition for Ethernet frame */ +#define ETH_MAX_PACKET_SIZE 1520 /* ETH_HEADER + ETH_EXTRA + MAX_ETH_PAYLOAD + ETH_CRC */ +#define ETH_HEADER 14 /* 6 byte Dest addr, 6 byte Src addr, 2 byte length/type */ +#define ETH_CRC 4 /* Ethernet CRC */ +#define ETH_EXTRA 2 /* Extra bytes in some cases */ +#define VLAN_TAG 4 /* optional 802.1q VLAN Tag */ +#define MIN_ETH_PAYLOAD 46 /* Minimum Ethernet payload size */ +#define MAX_ETH_PAYLOAD 1500 /* Maximum Ethernet payload size */ +#define JUMBO_FRAME_PAYLOAD 9000 /* Jumbo frame payload size */ + +/* ETH DMA structure definition */ +typedef struct +{ + uint32_t Status; /* Status */ + uint32_t ControlBufferSize; /* Control and Buffer1, Buffer2 lengths */ + uint32_t Buffer1Addr; /* Buffer1 address pointer */ + uint32_t Buffer2NextDescAddr; /* Buffer2 or next descriptor address pointer */ +} ETH_DMADESCTypeDef; + +/** + DMA Tx Desciptor + ----------------------------------------------------------------------------------------------- + TDES0 | OWN(31) | CTRL[30:26] | Reserved[25:24] | CTRL[23:20] | Reserved[19:17] | Status[16:0] | + ----------------------------------------------------------------------------------------------- + TDES1 | Reserved[31:29] | Buffer2 ByteCount[28:16] | Reserved[15:13] | Buffer1 ByteCount[12:0] | + ----------------------------------------------------------------------------------------------- + TDES2 | Buffer1 Address [31:0] | + ----------------------------------------------------------------------------------------------- + TDES3 | Buffer2 Address [31:0] / Next Desciptor Address [31:0] | + ------------------------------------------------------------------------------------------------ +*/ + + +/* Bit or field definition of TDES0 register (DMA Tx descriptor status register)*/ +#define ETH_DMATxDesc_OWN ((uint32_t)0x80000000) /* OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMATxDesc_IC ((uint32_t)0x40000000) /* Interrupt on Completion */ +#define ETH_DMATxDesc_LS ((uint32_t)0x20000000) /* Last Segment */ +#define ETH_DMATxDesc_FS ((uint32_t)0x10000000) /* First Segment */ +#define ETH_DMATxDesc_DC ((uint32_t)0x08000000) /* Disable CRC */ +#define ETH_DMATxDesc_DP ((uint32_t)0x04000000) /* Disable Padding */ +#define ETH_DMATxDesc_TTSE ((uint32_t)0x02000000) /* Transmit Time Stamp Enable */ +#define ETH_DMATxDesc_CIC ((uint32_t)0x00C00000) /* Checksum Insertion Control: 4 cases */ +#define ETH_DMATxDesc_CIC_ByPass ((uint32_t)0x00000000) /* Do Nothing: Checksum Engine is bypassed */ +#define ETH_DMATxDesc_CIC_IPV4Header ((uint32_t)0x00400000) /* IPV4 header Checksum Insertion */ +#define ETH_DMATxDesc_CIC_TCPUDPICMP_Segment ((uint32_t)0x00800000) /* TCP/UDP/ICMP Checksum Insertion calculated over segment only */ +#define ETH_DMATxDesc_CIC_TCPUDPICMP_Full ((uint32_t)0x00C00000) /* TCP/UDP/ICMP Checksum Insertion fully calculated */ +#define ETH_DMATxDesc_TER ((uint32_t)0x00200000) /* Transmit End of Ring */ +#define ETH_DMATxDesc_TCH ((uint32_t)0x00100000) /* Second Address Chained */ +#define ETH_DMATxDesc_TTSS ((uint32_t)0x00020000) /* Tx Time Stamp Status */ +#define ETH_DMATxDesc_IHE ((uint32_t)0x00010000) /* IP Header Error */ +#define ETH_DMATxDesc_ES ((uint32_t)0x00008000) /* Error summary: OR of the following bits: UE || ED || EC || LCO || NC || LCA || FF || JT */ +#define ETH_DMATxDesc_JT ((uint32_t)0x00004000) /* Jabber Timeout */ +#define ETH_DMATxDesc_FF ((uint32_t)0x00002000) /* Frame Flushed: DMA/MTL flushed the frame due to SW flush */ +#define ETH_DMATxDesc_PCE ((uint32_t)0x00001000) /* Payload Checksum Error */ +#define ETH_DMATxDesc_LCA ((uint32_t)0x00000800) /* Loss of Carrier: carrier lost during tramsmission */ +#define ETH_DMATxDesc_NC ((uint32_t)0x00000400) /* No Carrier: no carrier signal from the tranceiver */ +#define ETH_DMATxDesc_LCO ((uint32_t)0x00000200) /* Late Collision: transmission aborted due to collision */ +#define ETH_DMATxDesc_EC ((uint32_t)0x00000100) /* Excessive Collision: transmission aborted after 16 collisions */ +#define ETH_DMATxDesc_VF ((uint32_t)0x00000080) /* VLAN Frame */ +#define ETH_DMATxDesc_CC ((uint32_t)0x00000078) /* Collision Count */ +#define ETH_DMATxDesc_ED ((uint32_t)0x00000004) /* Excessive Deferral */ +#define ETH_DMATxDesc_UF ((uint32_t)0x00000002) /* Underflow Error: late data arrival from the memory */ +#define ETH_DMATxDesc_DB ((uint32_t)0x00000001) /* Deferred Bit */ + +/* Field definition of TDES1 register */ +#define ETH_DMATxDesc_TBS2 ((uint32_t)0x1FFF0000) /* Transmit Buffer2 Size */ +#define ETH_DMATxDesc_TBS1 ((uint32_t)0x00001FFF) /* Transmit Buffer1 Size */ + +/* Field definition of TDES2 register */ +#define ETH_DMATxDesc_B1AP ((uint32_t)0xFFFFFFFF) /* Buffer1 Address Pointer */ + +/* Field definition of TDES3 register */ +#define ETH_DMATxDesc_B2AP ((uint32_t)0xFFFFFFFF) /* Buffer2 Address Pointer */ + +/** + DMA Rx Desciptor + --------------------------------------------------------------------------------------------------------------------- + RDES0 | OWN(31) | Status [30:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES1 | CTRL(31) | Reserved[30:29] | Buffer2 ByteCount[28:16] | CTRL[15:14] | Reserved(13) | Buffer1 ByteCount[12:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES2 | Buffer1 Address [31:0] | + --------------------------------------------------------------------------------------------------------------------- + RDES3 | Buffer2 Address [31:0] / Next Desciptor Address [31:0] | + ---------------------------------------------------------------------------------------------------------------------- +*/ + +/* Bit or field definition of RDES0 register (DMA Rx descriptor status register) */ +#define ETH_DMARxDesc_OWN ((uint32_t)0x80000000) /* OWN bit: descriptor is owned by DMA engine */ +#define ETH_DMARxDesc_AFM ((uint32_t)0x40000000) /* DA Filter Fail for the rx frame */ +#define ETH_DMARxDesc_FL ((uint32_t)0x3FFF0000) /* Receive descriptor frame length */ +#define ETH_DMARxDesc_ES ((uint32_t)0x00008000) /* Error summary: OR of the following bits: DE || OE || IPC || LC || RWT || RE || CE */ +#define ETH_DMARxDesc_DE ((uint32_t)0x00004000) /* Desciptor error: no more descriptors for receive frame */ +#define ETH_DMARxDesc_SAF ((uint32_t)0x00002000) /* SA Filter Fail for the received frame */ +#define ETH_DMARxDesc_LE ((uint32_t)0x00001000) /* Frame size not matching with length field */ +#define ETH_DMARxDesc_OE ((uint32_t)0x00000800) /* Overflow Error: Frame was damaged due to buffer overflow */ +#define ETH_DMARxDesc_VLAN ((uint32_t)0x00000400) /* VLAN Tag: received frame is a VLAN frame */ +#define ETH_DMARxDesc_FS ((uint32_t)0x00000200) /* First descriptor of the frame */ +#define ETH_DMARxDesc_LS ((uint32_t)0x00000100) /* Last descriptor of the frame */ +#define ETH_DMARxDesc_IPV4HCE ((uint32_t)0x00000080) /* IPC Checksum Error: Rx Ipv4 header checksum error */ +#define ETH_DMARxDesc_LC ((uint32_t)0x00000040) /* Late collision occurred during reception */ +#define ETH_DMARxDesc_FT ((uint32_t)0x00000020) /* Frame type - Ethernet, otherwise 802.3 */ +#define ETH_DMARxDesc_RWT ((uint32_t)0x00000010) /* Receive Watchdog Timeout: watchdog timer expired during reception */ +#define ETH_DMARxDesc_RE ((uint32_t)0x00000008) /* Receive error: error reported by MII interface */ +#define ETH_DMARxDesc_DBE ((uint32_t)0x00000004) /* Dribble bit error: frame contains non int multiple of 8 bits */ +#define ETH_DMARxDesc_CE ((uint32_t)0x00000002) /* CRC error */ +#define ETH_DMARxDesc_MAMPCE ((uint32_t)0x00000001) /* Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum Error */ + +/* Bit or field definition of RDES1 register */ +#define ETH_DMARxDesc_DIC ((uint32_t)0x80000000) /* Disable Interrupt on Completion */ +#define ETH_DMARxDesc_RBS2 ((uint32_t)0x1FFF0000) /* Receive Buffer2 Size */ +#define ETH_DMARxDesc_RER ((uint32_t)0x00008000) /* Receive End of Ring */ +#define ETH_DMARxDesc_RCH ((uint32_t)0x00004000) /* Second Address Chained */ +#define ETH_DMARxDesc_RBS1 ((uint32_t)0x00001FFF) /* Receive Buffer1 Size */ + +/* Field definition of RDES2 register */ +#define ETH_DMARxDesc_B1AP ((uint32_t)0xFFFFFFFF) /* Buffer1 Address Pointer */ + +/* Field definition of RDES3 register */ +#define ETH_DMARxDesc_B2AP ((uint32_t)0xFFFFFFFF) /* Buffer2 Address Pointer */ + +/* Timeout threshold of Reading or writing PHY registers */ +#define PHY_READ_TO ((uint32_t)0x004FFFFF) +#define PHY_WRITE_TO ((uint32_t)0x0004FFFF) + +/* Delay time after reset PHY */ +#define PHY_ResetDelay ((uint32_t)0x000FFFFF) + +/* Delay time after configure PHY */ +#define PHY_ConfigDelay ((uint32_t)0x00FFFFFF) + +/* PHY basic register */ +#define PHY_BCR 0 /*PHY tranceiver Basic Control Register */ +#define PHY_BSR 1 /*PHY tranceiver Basic Status Register */ +#define PHY_BMCR PHY_BCR +#define PHY_BMSR PHY_BSR + +/* Bit or field definition for PHY basic control register */ +#define PHY_Reset ((uint16_t)0x8000) /* PHY Reset */ +#define PHY_Loopback ((uint16_t)0x4000) /* Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100) /* Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000) /* Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100) /* Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000) /* Set the half-duplex mode at 10 Mb/s */ +#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) /* Select the power down mode */ +#define PHY_Isolate ((uint16_t)0x0400) /* Isolate PHY from MII */ + +/* Bit or field definition for 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 */ +#define PHY_RMII_Mode ((uint16_t)0x0020) /* RMII */ + + +/* Internal 10BASE-T PHY 50R*4 pull-up resistance enable or disable */ +#define ETH_Internal_Pull_Up_Res_Enable ((uint32_t)0x00100000) +#define ETH_Internal_Pull_Up_Res_Disable ((uint32_t)0x00000000) + +/* MAC autoNegotiation enable or disable */ +#define ETH_AutoNegotiation_Enable ((uint32_t)0x00000001) +#define ETH_AutoNegotiation_Disable ((uint32_t)0x00000000) + +/* MAC watchdog enable or disable */ +#define ETH_Watchdog_Enable ((uint32_t)0x00000000) +#define ETH_Watchdog_Disable ((uint32_t)0x00800000) + +/* Bit description : MAC jabber enable or disable */ +#define ETH_Jabber_Enable ((uint32_t)0x00000000) +#define ETH_Jabber_Disable ((uint32_t)0x00400000) + +/* Value of minimum IFG between frames during transmission */ +#define ETH_InterFrameGap_96Bit ((uint32_t)0x00000000) /* minimum IFG between frames during transmission is 96Bit */ +#define ETH_InterFrameGap_88Bit ((uint32_t)0x00020000) /* minimum IFG between frames during transmission is 88Bit */ +#define ETH_InterFrameGap_80Bit ((uint32_t)0x00040000) /* minimum IFG between frames during transmission is 80Bit */ +#define ETH_InterFrameGap_72Bit ((uint32_t)0x00060000) /* minimum IFG between frames during transmission is 72Bit */ +#define ETH_InterFrameGap_64Bit ((uint32_t)0x00080000) /* minimum IFG between frames during transmission is 64Bit */ +#define ETH_InterFrameGap_56Bit ((uint32_t)0x000A0000) /* minimum IFG between frames during transmission is 56Bit */ +#define ETH_InterFrameGap_48Bit ((uint32_t)0x000C0000) /* minimum IFG between frames during transmission is 48Bit */ +#define ETH_InterFrameGap_40Bit ((uint32_t)0x000E0000) /* minimum IFG between frames during transmission is 40Bit */ + +/* MAC carrier sense enable or disable */ +#define ETH_CarrierSense_Enable ((uint32_t)0x00000000) +#define ETH_CarrierSense_Disable ((uint32_t)0x00010000) + +/* MAC speed */ +#define ETH_Speed_10M ((uint32_t)0x00000000) +#define ETH_Speed_100M ((uint32_t)0x00004000) +#define ETH_Speed_1000M ((uint32_t)0x00008000) + +/* MAC receive own enable or disable */ +#define ETH_ReceiveOwn_Enable ((uint32_t)0x00000000) +#define ETH_ReceiveOwn_Disable ((uint32_t)0x00002000) + +/* MAC Loopback mode enable or disable */ +#define ETH_LoopbackMode_Enable ((uint32_t)0x00001000) +#define ETH_LoopbackMode_Disable ((uint32_t)0x00000000) + +/* MAC fullDuplex or halfDuplex */ +#define ETH_Mode_FullDuplex ((uint32_t)0x00000800) +#define ETH_Mode_HalfDuplex ((uint32_t)0x00000000) + +/* MAC offload checksum enable or disable */ +#define ETH_ChecksumOffload_Enable ((uint32_t)0x00000400) +#define ETH_ChecksumOffload_Disable ((uint32_t)0x00000000) + +/* MAC transmission retry enable or disable */ +#define ETH_RetryTransmission_Enable ((uint32_t)0x00000000) +#define ETH_RetryTransmission_Disable ((uint32_t)0x00000200) + +/* MAC automatic pad CRC strip enable or disable */ +#define ETH_AutomaticPadCRCStrip_Enable ((uint32_t)0x00000080) +#define ETH_AutomaticPadCRCStrip_Disable ((uint32_t)0x00000000) + +/* MAC backoff limitation */ +#define ETH_BackOffLimit_10 ((uint32_t)0x00000000) +#define ETH_BackOffLimit_8 ((uint32_t)0x00000020) +#define ETH_BackOffLimit_4 ((uint32_t)0x00000040) +#define ETH_BackOffLimit_1 ((uint32_t)0x00000060) + +/* MAC deferral check enable or disable */ +#define ETH_DeferralCheck_Enable ((uint32_t)0x00000010) +#define ETH_DeferralCheck_Disable ((uint32_t)0x00000000) + +/* Bit description : MAC receive all frame enable or disable */ +#define ETH_ReceiveAll_Enable ((uint32_t)0x80000000) +#define ETH_ReceiveAll_Disable ((uint32_t)0x00000000) + +/* MAC backoff limitation */ +#define ETH_SourceAddrFilter_Normal_Enable ((uint32_t)0x00000200) +#define ETH_SourceAddrFilter_Inverse_Enable ((uint32_t)0x00000300) +#define ETH_SourceAddrFilter_Disable ((uint32_t)0x00000000) + +/* MAC Pass control frames */ +#define ETH_PassControlFrames_BlockAll ((uint32_t)0x00000040) /* MAC filters all control frames from reaching the application */ +#define ETH_PassControlFrames_ForwardAll ((uint32_t)0x00000080) /* MAC forwards all control frames to application even if they fail the Address Filter */ +#define ETH_PassControlFrames_ForwardPassedAddrFilter ((uint32_t)0x000000C0) /* MAC forwards control frames that pass the Address Filter. */ + +/* MAC broadcast frames reception */ +#define ETH_BroadcastFramesReception_Enable ((uint32_t)0x00000000) +#define ETH_BroadcastFramesReception_Disable ((uint32_t)0x00000020) + +/* MAC destination address filter */ +#define ETH_DestinationAddrFilter_Normal ((uint32_t)0x00000000) +#define ETH_DestinationAddrFilter_Inverse ((uint32_t)0x00000008) + +/* MAC Promiscuous mode enable or disable */ +#define ETH_PromiscuousMode_Enable ((uint32_t)0x00000001) +#define ETH_PromiscuousMode_Disable ((uint32_t)0x00000000) + +/* MAC multicast frames filter */ +#define ETH_MulticastFramesFilter_PerfectHashTable ((uint32_t)0x00000404) +#define ETH_MulticastFramesFilter_HashTable ((uint32_t)0x00000004) +#define ETH_MulticastFramesFilter_Perfect ((uint32_t)0x00000000) +#define ETH_MulticastFramesFilter_None ((uint32_t)0x00000010) + +/* MAC unicast frames filter */ +#define ETH_UnicastFramesFilter_PerfectHashTable ((uint32_t)0x00000402) +#define ETH_UnicastFramesFilter_HashTable ((uint32_t)0x00000002) +#define ETH_UnicastFramesFilter_Perfect ((uint32_t)0x00000000) + +/* Bit description : MAC zero quanta pause */ +#define ETH_ZeroQuantaPause_Enable ((uint32_t)0x00000000) +#define ETH_ZeroQuantaPause_Disable ((uint32_t)0x00000080) + +/* Field description : MAC pause low threshold */ +#define ETH_PauseLowThreshold_Minus4 ((uint32_t)0x00000000) /* Pause time minus 4 slot times */ +#define ETH_PauseLowThreshold_Minus28 ((uint32_t)0x00000010) /* Pause time minus 28 slot times */ +#define ETH_PauseLowThreshold_Minus144 ((uint32_t)0x00000020) /* Pause time minus 144 slot times */ +#define ETH_PauseLowThreshold_Minus256 ((uint32_t)0x00000030) /* Pause time minus 256 slot times */ + +/* MAC unicast pause frame detect enable or disable*/ +#define ETH_UnicastPauseFrameDetect_Enable ((uint32_t)0x00000008) +#define ETH_UnicastPauseFrameDetect_Disable ((uint32_t)0x00000000) + +/* MAC receive flow control frame enable or disable */ +#define ETH_ReceiveFlowControl_Enable ((uint32_t)0x00000004) +#define ETH_ReceiveFlowControl_Disable ((uint32_t)0x00000000) + +/* MAC transmit flow control enable or disable */ +#define ETH_TransmitFlowControl_Enable ((uint32_t)0x00000002) +#define ETH_TransmitFlowControl_Disable ((uint32_t)0x00000000) + +/* MAC VLAN tag comparison */ +#define ETH_VLANTagComparison_12Bit ((uint32_t)0x00010000) +#define ETH_VLANTagComparison_16Bit ((uint32_t)0x00000000) + +/* MAC flag */ +#define ETH_MAC_FLAG_TST ((uint32_t)0x00000200) /* Time stamp trigger flag (on MAC) */ +#define ETH_MAC_FLAG_MMCT ((uint32_t)0x00000040) /* MMC transmit flag */ +#define ETH_MAC_FLAG_MMCR ((uint32_t)0x00000020) /* MMC receive flag */ +#define ETH_MAC_FLAG_MMC ((uint32_t)0x00000010) /* MMC flag (on MAC) */ +#define ETH_MAC_FLAG_PMT ((uint32_t)0x00000008) /* PMT flag (on MAC) */ + +/* MAC interrupt */ +#define ETH_MAC_IT_TST ((uint32_t)0x00000200) /* Time stamp trigger interrupt (on MAC) */ +#define ETH_MAC_IT_MMCT ((uint32_t)0x00000040) /* MMC transmit interrupt */ +#define ETH_MAC_IT_MMCR ((uint32_t)0x00000020) /* MMC receive interrupt */ +#define ETH_MAC_IT_MMC ((uint32_t)0x00000010) /* MMC interrupt (on MAC) */ +#define ETH_MAC_IT_PMT ((uint32_t)0x00000008) /* PMT interrupt (on MAC) */ + +/* MAC address */ +#define ETH_MAC_Address0 ((uint32_t)0x00000000) +#define ETH_MAC_Address1 ((uint32_t)0x00000008) +#define ETH_MAC_Address2 ((uint32_t)0x00000010) +#define ETH_MAC_Address3 ((uint32_t)0x00000018) + +/* MAC address filter select */ +#define ETH_MAC_AddressFilter_SA ((uint32_t)0x00000000) +#define ETH_MAC_AddressFilter_DA ((uint32_t)0x00000008) + +/* MAC address mask */ +#define ETH_MAC_AddressMask_Byte6 ((uint32_t)0x20000000) /* Mask MAC Address high reg bits [15:8] */ +#define ETH_MAC_AddressMask_Byte5 ((uint32_t)0x10000000) /* Mask MAC Address high reg bits [7:0] */ +#define ETH_MAC_AddressMask_Byte4 ((uint32_t)0x08000000) /* Mask MAC Address low reg bits [31:24] */ +#define ETH_MAC_AddressMask_Byte3 ((uint32_t)0x04000000) /* Mask MAC Address low reg bits [23:16] */ +#define ETH_MAC_AddressMask_Byte2 ((uint32_t)0x02000000) /* Mask MAC Address low reg bits [15:8] */ +#define ETH_MAC_AddressMask_Byte1 ((uint32_t)0x01000000) /* Mask MAC Address low reg bits [70] */ + + +/******************************************************************************/ +/* */ +/* MAC Descriptor Register */ +/* */ +/******************************************************************************/ + +/* DMA descriptor segment */ +#define ETH_DMATxDesc_LastSegment ((uint32_t)0x40000000) /* Last Segment */ +#define ETH_DMATxDesc_FirstSegment ((uint32_t)0x20000000) /* First Segment */ + +/* DMA descriptor checksum setting */ +#define ETH_DMATxDesc_ChecksumByPass ((uint32_t)0x00000000) /* Checksum engine bypass */ +#define ETH_DMATxDesc_ChecksumIPV4Header ((uint32_t)0x00400000) /* IPv4 header checksum insertion */ +#define ETH_DMATxDesc_ChecksumTCPUDPICMPSegment ((uint32_t)0x00800000) /* TCP/UDP/ICMP checksum insertion. Pseudo header checksum is assumed to be present */ +#define ETH_DMATxDesc_ChecksumTCPUDPICMPFull ((uint32_t)0x00C00000) /* TCP/UDP/ICMP checksum fully in hardware including pseudo header */ + +/* DMA RX & TX buffer */ +#define ETH_DMARxDesc_Buffer1 ((uint32_t)0x00000000) /* DMA Rx Desc Buffer1 */ +#define ETH_DMARxDesc_Buffer2 ((uint32_t)0x00000001) /* DMA Rx Desc Buffer2 */ + + +/******************************************************************************/ +/* */ +/* ETH DMA Register */ +/* */ +/******************************************************************************/ + +/* DMA drop TCPIP checksum error frame enable or disable */ +#define ETH_DropTCPIPChecksumErrorFrame_Enable ((uint32_t)0x00000000) +#define ETH_DropTCPIPChecksumErrorFrame_Disable ((uint32_t)0x04000000) + +/* DMA receive store forward enable or disable */ +#define ETH_ReceiveStoreForward_Enable ((uint32_t)0x02000000) +#define ETH_ReceiveStoreForward_Disable ((uint32_t)0x00000000) + +/* DMA flush received frame enable or disable */ +#define ETH_FlushReceivedFrame_Enable ((uint32_t)0x00000000) +#define ETH_FlushReceivedFrame_Disable ((uint32_t)0x01000000) + +/* DMA transmit store forward enable or disable */ +#define ETH_TransmitStoreForward_Enable ((uint32_t)0x00200000) +#define ETH_TransmitStoreForward_Disable ((uint32_t)0x00000000) + +/* DMA transmit threshold control */ +#define ETH_TransmitThresholdControl_64Bytes ((uint32_t)0x00000000) /* threshold level of the MTL Transmit FIFO is 64 Bytes */ +#define ETH_TransmitThresholdControl_128Bytes ((uint32_t)0x00004000) /* threshold level of the MTL Transmit FIFO is 128 Bytes */ +#define ETH_TransmitThresholdControl_192Bytes ((uint32_t)0x00008000) /* threshold level of the MTL Transmit FIFO is 192 Bytes */ +#define ETH_TransmitThresholdControl_256Bytes ((uint32_t)0x0000C000) /* threshold level of the MTL Transmit FIFO is 256 Bytes */ +#define ETH_TransmitThresholdControl_40Bytes ((uint32_t)0x00010000) /* threshold level of the MTL Transmit FIFO is 40 Bytes */ +#define ETH_TransmitThresholdControl_32Bytes ((uint32_t)0x00014000) /* threshold level of the MTL Transmit FIFO is 32 Bytes */ +#define ETH_TransmitThresholdControl_24Bytes ((uint32_t)0x00018000) /* threshold level of the MTL Transmit FIFO is 24 Bytes */ +#define ETH_TransmitThresholdControl_16Bytes ((uint32_t)0x0001C000) /* threshold level of the MTL Transmit FIFO is 16 Bytes */ + +/* DMA forward error frames */ +#define ETH_ForwardErrorFrames_Enable ((uint32_t)0x00000080) +#define ETH_ForwardErrorFrames_Disable ((uint32_t)0x00000000) + +/* DMA forward undersized good frames enable or disable */ +#define ETH_ForwardUndersizedGoodFrames_Enable ((uint32_t)0x00000040) +#define ETH_ForwardUndersizedGoodFrames_Disable ((uint32_t)0x00000000) + +/* DMA receive threshold control */ +#define ETH_ReceiveThresholdControl_64Bytes ((uint32_t)0x00000000) /* threshold level of the MTL Receive FIFO is 64 Bytes */ +#define ETH_ReceiveThresholdControl_32Bytes ((uint32_t)0x00000008) /* threshold level of the MTL Receive FIFO is 32 Bytes */ +#define ETH_ReceiveThresholdControl_96Bytes ((uint32_t)0x00000010) /* threshold level of the MTL Receive FIFO is 96 Bytes */ +#define ETH_ReceiveThresholdControl_128Bytes ((uint32_t)0x00000018) /* threshold level of the MTL Receive FIFO is 128 Bytes */ + +/* DMA second frame operate enable or disable */ +#define ETH_SecondFrameOperate_Enable ((uint32_t)0x00000004) +#define ETH_SecondFrameOperate_Disable ((uint32_t)0x00000000) + +/* Address aligned beats enable or disable */ +#define ETH_AddressAlignedBeats_Enable ((uint32_t)0x02000000) +#define ETH_AddressAlignedBeats_Disable ((uint32_t)0x00000000) + +/* DMA Fixed burst enable or disable */ +#define ETH_FixedBurst_Enable ((uint32_t)0x00010000) +#define ETH_FixedBurst_Disable ((uint32_t)0x00000000) + + +/* RX DMA burst length */ +#define ETH_RxDMABurstLength_1Beat ((uint32_t)0x00020000) /* maximum number of beats to be transferred in one RxDMA transaction is 1 */ +#define ETH_RxDMABurstLength_2Beat ((uint32_t)0x00040000) /* maximum number of beats to be transferred in one RxDMA transaction is 2 */ +#define ETH_RxDMABurstLength_4Beat ((uint32_t)0x00080000) /* maximum number of beats to be transferred in one RxDMA transaction is 4 */ +#define ETH_RxDMABurstLength_8Beat ((uint32_t)0x00100000) /* maximum number of beats to be transferred in one RxDMA transaction is 8 */ +#define ETH_RxDMABurstLength_16Beat ((uint32_t)0x00200000) /* maximum number of beats to be transferred in one RxDMA transaction is 16 */ +#define ETH_RxDMABurstLength_32Beat ((uint32_t)0x00400000) /* maximum number of beats to be transferred in one RxDMA transaction is 32 */ +#define ETH_RxDMABurstLength_4xPBL_4Beat ((uint32_t)0x01020000) /* maximum number of beats to be transferred in one RxDMA transaction is 4 */ +#define ETH_RxDMABurstLength_4xPBL_8Beat ((uint32_t)0x01040000) /* maximum number of beats to be transferred in one RxDMA transaction is 8 */ +#define ETH_RxDMABurstLength_4xPBL_16Beat ((uint32_t)0x01080000) /* maximum number of beats to be transferred in one RxDMA transaction is 16 */ +#define ETH_RxDMABurstLength_4xPBL_32Beat ((uint32_t)0x01100000) /* maximum number of beats to be transferred in one RxDMA transaction is 32 */ +#define ETH_RxDMABurstLength_4xPBL_64Beat ((uint32_t)0x01200000) /* maximum number of beats to be transferred in one RxDMA transaction is 64 */ +#define ETH_RxDMABurstLength_4xPBL_128Beat ((uint32_t)0x01400000) /* maximum number of beats to be transferred in one RxDMA transaction is 128 */ + + +/* TX DMA burst length */ +#define ETH_TxDMABurstLength_1Beat ((uint32_t)0x00000100) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 1 */ +#define ETH_TxDMABurstLength_2Beat ((uint32_t)0x00000200) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 2 */ +#define ETH_TxDMABurstLength_4Beat ((uint32_t)0x00000400) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ +#define ETH_TxDMABurstLength_8Beat ((uint32_t)0x00000800) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ +#define ETH_TxDMABurstLength_16Beat ((uint32_t)0x00001000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ +#define ETH_TxDMABurstLength_32Beat ((uint32_t)0x00002000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ +#define ETH_TxDMABurstLength_4xPBL_4Beat ((uint32_t)0x01000100) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ +#define ETH_TxDMABurstLength_4xPBL_8Beat ((uint32_t)0x01000200) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ +#define ETH_TxDMABurstLength_4xPBL_16Beat ((uint32_t)0x01000400) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ +#define ETH_TxDMABurstLength_4xPBL_32Beat ((uint32_t)0x01000800) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ +#define ETH_TxDMABurstLength_4xPBL_64Beat ((uint32_t)0x01001000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 64 */ +#define ETH_TxDMABurstLength_4xPBL_128Beat ((uint32_t)0x01002000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 128 */ + +/* DMA arbitration_round robin */ +#define ETH_DMAArbitration_RoundRobin_RxTx_1_1 ((uint32_t)0x00000000) +#define ETH_DMAArbitration_RoundRobin_RxTx_2_1 ((uint32_t)0x00004000) +#define ETH_DMAArbitration_RoundRobin_RxTx_3_1 ((uint32_t)0x00008000) +#define ETH_DMAArbitration_RoundRobin_RxTx_4_1 ((uint32_t)0x0000C000) +#define ETH_DMAArbitration_RxPriorTx ((uint32_t)0x00000002) + +/* DMA interrupt FALG */ +#define ETH_DMA_FLAG_TST ((uint32_t)0x20000000) /* Time-stamp trigger interrupt (on DMA) */ +#define ETH_DMA_FLAG_PMT ((uint32_t)0x10000000) /* PMT interrupt (on DMA) */ +#define ETH_DMA_FLAG_MMC ((uint32_t)0x08000000) /* MMC interrupt (on DMA) */ +#define ETH_DMA_FLAG_DataTransferError ((uint32_t)0x00800000) /* Error bits 0-Rx DMA, 1-Tx DMA */ +#define ETH_DMA_FLAG_ReadWriteError ((uint32_t)0x01000000) /* Error bits 0-write trnsf, 1-read transfr */ +#define ETH_DMA_FLAG_AccessError ((uint32_t)0x02000000) /* Error bits 0-data buffer, 1-desc. access */ +#define ETH_DMA_FLAG_NIS ((uint32_t)0x00010000) /* Normal interrupt summary flag */ +#define ETH_DMA_FLAG_AIS ((uint32_t)0x00008000) /* Abnormal interrupt summary flag */ +#define ETH_DMA_FLAG_ER ((uint32_t)0x00004000) /* Early receive flag */ +#define ETH_DMA_FLAG_FBE ((uint32_t)0x00002000) /* Fatal bus error flag */ +#define ETH_DMA_FLAG_ET ((uint32_t)0x00000400) /* Early transmit flag */ +#define ETH_DMA_FLAG_RWT ((uint32_t)0x00000200) /* Receive watchdog timeout flag */ +#define ETH_DMA_FLAG_RPS ((uint32_t)0x00000100) /* Receive process stopped flag */ +#define ETH_DMA_FLAG_RBU ((uint32_t)0x00000080) /* Receive buffer unavailable flag */ +#define ETH_DMA_FLAG_R ((uint32_t)0x00000040) /* Receive flag */ +#define ETH_DMA_FLAG_TU ((uint32_t)0x00000020) /* Underflow flag */ +#define ETH_DMA_FLAG_RO ((uint32_t)0x00000010) /* Overflow flag */ +#define ETH_DMA_FLAG_TJT ((uint32_t)0x00000008) /* Transmit jabber timeout flag */ +#define ETH_DMA_FLAG_TBU ((uint32_t)0x00000004) /* Transmit buffer unavailable flag */ +#define ETH_DMA_FLAG_TPS ((uint32_t)0x00000002) /* Transmit process stopped flag */ +#define ETH_DMA_FLAG_T ((uint32_t)0x00000001) /* Transmit flag */ + +/* DMA interrupt */ +#define ETH_DMA_IT_PHYLINK ((uint32_t)0x80000000) /* Internal PHY link status change interrupt */ +#define ETH_DMA_IT_TST ((uint32_t)0x20000000) /* Time-stamp trigger interrupt (on DMA) */ +#define ETH_DMA_IT_PMT ((uint32_t)0x10000000) /* PMT interrupt (on DMA) */ +#define ETH_DMA_IT_MMC ((uint32_t)0x08000000) /* MMC interrupt (on DMA) */ +#define ETH_DMA_IT_NIS ((uint32_t)0x00010000) /* Normal interrupt summary */ +#define ETH_DMA_IT_AIS ((uint32_t)0x00008000) /* Abnormal interrupt summary */ +#define ETH_DMA_IT_ER ((uint32_t)0x00004000) /* Early receive interrupt */ +#define ETH_DMA_IT_FBE ((uint32_t)0x00002000) /* Fatal bus error interrupt */ +#define ETH_DMA_IT_ET ((uint32_t)0x00000400) /* Early transmit interrupt */ +#define ETH_DMA_IT_RWT ((uint32_t)0x00000200) /* Receive watchdog timeout interrupt */ +#define ETH_DMA_IT_RPS ((uint32_t)0x00000100) /* Receive process stopped interrupt */ +#define ETH_DMA_IT_RBU ((uint32_t)0x00000080) /* Receive buffer unavailable interrupt */ +#define ETH_DMA_IT_R ((uint32_t)0x00000040) /* Receive interrupt */ +#define ETH_DMA_IT_TU ((uint32_t)0x00000020) /* Underflow interrupt */ +#define ETH_DMA_IT_RO ((uint32_t)0x00000010) /* Overflow interrupt */ +#define ETH_DMA_IT_TJT ((uint32_t)0x00000008) /* Transmit jabber timeout interrupt */ +#define ETH_DMA_IT_TBU ((uint32_t)0x00000004) /* Transmit buffer unavailable interrupt */ +#define ETH_DMA_IT_TPS ((uint32_t)0x00000002) /* Transmit process stopped interrupt */ +#define ETH_DMA_IT_T ((uint32_t)0x00000001) /* Transmit interrupt */ + +/* DMA transmit process */ +#define ETH_DMA_TransmitProcess_Stopped ((uint32_t)0x00000000) /* Stopped - Reset or Stop Tx Command issued */ +#define ETH_DMA_TransmitProcess_Fetching ((uint32_t)0x00100000) /* Running - fetching the Tx descriptor */ +#define ETH_DMA_TransmitProcess_Waiting ((uint32_t)0x00200000) /* Running - waiting for status */ +#define ETH_DMA_TransmitProcess_Reading ((uint32_t)0x00300000) /* Running - reading the data from host memory */ +#define ETH_DMA_TransmitProcess_Suspended ((uint32_t)0x00600000) /* Suspended - Tx Desciptor unavailabe */ +#define ETH_DMA_TransmitProcess_Closing ((uint32_t)0x00700000) /* Running - closing Rx descriptor */ + +/* DMA receive Process */ +#define ETH_DMA_ReceiveProcess_Stopped ((uint32_t)0x00000000) /* Stopped - Reset or Stop Rx Command issued */ +#define ETH_DMA_ReceiveProcess_Fetching ((uint32_t)0x00020000) /* Running - fetching the Rx descriptor */ +#define ETH_DMA_ReceiveProcess_Waiting ((uint32_t)0x00060000) /* Running - waiting for packet */ +#define ETH_DMA_ReceiveProcess_Suspended ((uint32_t)0x00080000) /* Suspended - Rx Desciptor unavailable */ +#define ETH_DMA_ReceiveProcess_Closing ((uint32_t)0x000A0000) /* Running - closing descriptor */ +#define ETH_DMA_ReceiveProcess_Queuing ((uint32_t)0x000E0000) /* Running - queuing the recieve frame into host memory */ + +/* DMA overflow */ +#define ETH_DMA_Overflow_RxFIFOCounter ((uint32_t)0x10000000) /* Overflow bit for FIFO overflow counter */ +#define ETH_DMA_Overflow_MissedFrameCounter ((uint32_t)0x00010000) /* Overflow bit for missed frame counter */ + + +/********************************************************************************* +* Ethernet PMT defines +**********************************************************************************/ + +/* PMT flag */ +#define ETH_PMT_FLAG_WUFFRPR ((uint32_t)0x80000000) /* Wake-Up Frame Filter Register Poniter Reset */ +#define ETH_PMT_FLAG_WUFR ((uint32_t)0x00000040) /* Wake-Up Frame Received */ +#define ETH_PMT_FLAG_MPR ((uint32_t)0x00000020) /* Magic Packet Received */ + +/********************************************************************************* +* Ethernet MMC defines +**********************************************************************************/ + +/* MMC TX interrupt flag */ +#define ETH_MMC_IT_TGF ((uint32_t)0x00200000) /* When Tx good frame counter reaches half the maximum value */ +#define ETH_MMC_IT_TGFMSC ((uint32_t)0x00008000) /* When Tx good multi col counter reaches half the maximum value */ +#define ETH_MMC_IT_TGFSC ((uint32_t)0x00004000) /* When Tx good single col counter reaches half the maximum value */ + +/* MMC RX interrupt flag */ +#define ETH_MMC_IT_RGUF ((uint32_t)0x10020000) /* When Rx good unicast frames counter reaches half the maximum value */ +#define ETH_MMC_IT_RFAE ((uint32_t)0x10000040) /* When Rx alignment error counter reaches half the maximum value */ +#define ETH_MMC_IT_RFCE ((uint32_t)0x10000020) /* When Rx crc error counter reaches half the maximum value */ + + +/* MMC description */ +#define ETH_MMCCR ((uint32_t)0x00000100) /* MMC CR register */ +#define ETH_MMCRIR ((uint32_t)0x00000104) /* MMC RIR register */ +#define ETH_MMCTIR ((uint32_t)0x00000108) /* MMC TIR register */ +#define ETH_MMCRIMR ((uint32_t)0x0000010C) /* MMC RIMR register */ +#define ETH_MMCTIMR ((uint32_t)0x00000110) /* MMC TIMR register */ +#define ETH_MMCTGFSCCR ((uint32_t)0x0000014C) /* MMC TGFSCCR register */ +#define ETH_MMCTGFMSCCR ((uint32_t)0x00000150) /* MMC TGFMSCCR register */ +#define ETH_MMCTGFCR ((uint32_t)0x00000168) /* MMC TGFCR register */ +#define ETH_MMCRFCECR ((uint32_t)0x00000194) /* MMC RFCECR register */ +#define ETH_MMCRFAECR ((uint32_t)0x00000198) /* MMC RFAECR register */ +#define ETH_MMCRGUFCR ((uint32_t)0x000001C4) /* MMC RGUFCR register */ + + +/********************************************************************************* +* Ethernet PTP defines +**********************************************************************************/ + +/* PTP fine update method or coarse Update method */ +#define ETH_PTP_FineUpdate ((uint32_t)0x00000001) /* Fine Update method */ +#define ETH_PTP_CoarseUpdate ((uint32_t)0x00000000) /* Coarse Update method */ + + +/* PTP time stamp control */ +#define ETH_PTP_FLAG_TSARU ((uint32_t)0x00000020) /* Addend Register Update */ +#define ETH_PTP_FLAG_TSITE ((uint32_t)0x00000010) /* Time Stamp Interrupt Trigger */ +#define ETH_PTP_FLAG_TSSTU ((uint32_t)0x00000008) /* Time Stamp Update */ +#define ETH_PTP_FLAG_TSSTI ((uint32_t)0x00000004) /* Time Stamp Initialize */ + +/* PTP positive/negative time value */ +#define ETH_PTP_PositiveTime ((uint32_t)0x00000000) /* Positive time value */ +#define ETH_PTP_NegativeTime ((uint32_t)0x80000000) /* Negative time value */ + + +/******************************************************************************/ +/* */ +/* PTP Register */ +/* */ +/******************************************************************************/ +#define ETH_PTPTSCR ((uint32_t)0x00000700) /* PTP TSCR register */ +#define ETH_PTPSSIR ((uint32_t)0x00000704) /* PTP SSIR register */ +#define ETH_PTPTSHR ((uint32_t)0x00000708) /* PTP TSHR register */ +#define ETH_PTPTSLR ((uint32_t)0x0000070C) /* PTP TSLR register */ +#define ETH_PTPTSHUR ((uint32_t)0x00000710) /* PTP TSHUR register */ +#define ETH_PTPTSLUR ((uint32_t)0x00000714) /* PTP TSLUR register */ +#define ETH_PTPTSAR ((uint32_t)0x00000718) /* PTP TSAR register */ +#define ETH_PTPTTHR ((uint32_t)0x0000071C) /* PTP TTHR register */ +#define ETH_PTPTTLR ((uint32_t)0x00000720) /* PTP TTLR register */ + +#define ETH_DMASR_TSTS ((unsigned int)0x20000000) /* Time-stamp trigger status */ +#define ETH_DMASR_PMTS ((unsigned int)0x10000000) /* PMT status */ +#define ETH_DMASR_MMCS ((unsigned int)0x08000000) /* MMC status */ +#define ETH_DMASR_EBS ((unsigned int)0x03800000) /* Error bits status */ + #define ETH_DMASR_EBS_DescAccess ((unsigned int)0x02000000) /* Error bits 0-data buffer, 1-desc. access */ + #define ETH_DMASR_EBS_ReadTransf ((unsigned int)0x01000000) /* Error bits 0-write trnsf, 1-read transfr */ + #define ETH_DMASR_EBS_DataTransfTx ((unsigned int)0x00800000) /* Error bits 0-Rx DMA, 1-Tx DMA */ +#define ETH_DMASR_TPS ((unsigned int)0x00700000) /* Transmit process state */ + #define ETH_DMASR_TPS_Stopped ((unsigned int)0x00000000) /* Stopped - Reset or Stop Tx Command issued */ + #define ETH_DMASR_TPS_Fetching ((unsigned int)0x00100000) /* Running - fetching the Tx descriptor */ + #define ETH_DMASR_TPS_Waiting ((unsigned int)0x00200000) /* Running - waiting for status */ + #define ETH_DMASR_TPS_Reading ((unsigned int)0x00300000) /* Running - reading the data from host memory */ + #define ETH_DMASR_TPS_Suspended ((unsigned int)0x00600000) /* Suspended - Tx Descriptor unavailabe */ + #define ETH_DMASR_TPS_Closing ((unsigned int)0x00700000) /* Running - closing Rx descriptor */ +#define ETH_DMASR_RPS ((unsigned int)0x000E0000) /* Receive process state */ + #define ETH_DMASR_RPS_Stopped ((unsigned int)0x00000000) /* Stopped - Reset or Stop Rx Command issued */ + #define ETH_DMASR_RPS_Fetching ((unsigned int)0x00020000) /* Running - fetching the Rx descriptor */ + #define ETH_DMASR_RPS_Waiting ((unsigned int)0x00060000) /* Running - waiting for packet */ + #define ETH_DMASR_RPS_Suspended ((unsigned int)0x00080000) /* Suspended - Rx Descriptor unavailable */ + #define ETH_DMASR_RPS_Closing ((unsigned int)0x000A0000) /* Running - closing descriptor */ + #define ETH_DMASR_RPS_Queuing ((unsigned int)0x000E0000) /* Running - queuing the recieve frame into host memory */ +#define ETH_DMASR_NIS ((unsigned int)0x00010000) /* Normal interrupt summary */ +#define ETH_DMASR_AIS ((unsigned int)0x00008000) /* Abnormal interrupt summary */ +#define ETH_DMASR_ERS ((unsigned int)0x00004000) /* Early receive status */ +#define ETH_DMASR_FBES ((unsigned int)0x00002000) /* Fatal bus error status */ +#define ETH_DMASR_ETS ((unsigned int)0x00000400) /* Early transmit status */ +#define ETH_DMASR_RWTS ((unsigned int)0x00000200) /* Receive watchdog timeout status */ +#define ETH_DMASR_RPSS ((unsigned int)0x00000100) /* Receive process stopped status */ +#define ETH_DMASR_RBUS ((unsigned int)0x00000080) /* Receive buffer unavailable status */ +#define ETH_DMASR_RS ((unsigned int)0x00000040) /* Receive status */ +#define ETH_DMASR_TUS ((unsigned int)0x00000020) /* Transmit underflow status */ +#define ETH_DMASR_ROS ((unsigned int)0x00000010) /* Receive overflow status */ +#define ETH_DMASR_TJTS ((unsigned int)0x00000008) /* Transmit jabber timeout status */ +#define ETH_DMASR_TBUS ((unsigned int)0x00000004) /* Transmit buffer unavailable status */ +#define ETH_DMASR_TPSS ((unsigned int)0x00000002) /* Transmit process stopped status */ +#define ETH_DMASR_TS ((unsigned int)0x00000001) /* Transmit status */ + + +/******************************************************************************/ +/* */ +/* ETH MAC Register */ +/* */ +/******************************************************************************/ +#define ETH_MACCR_WD ((unsigned int)0x00800000) /* Watchdog disable */ +#define ETH_MACCR_JD ((unsigned int)0x00400000) /* Jabber disable */ +#define ETH_MACCR_IFG ((unsigned int)0x000E0000) /* Inter-frame gap */ +#define ETH_MACCR_IFG_96Bit ((unsigned int)0x00000000) /* Minimum IFG between frames during transmission is 96Bit */ + #define ETH_MACCR_IFG_88Bit ((unsigned int)0x00020000) /* Minimum IFG between frames during transmission is 88Bit */ + #define ETH_MACCR_IFG_80Bit ((unsigned int)0x00040000) /* Minimum IFG between frames during transmission is 80Bit */ + #define ETH_MACCR_IFG_72Bit ((unsigned int)0x00060000) /* Minimum IFG between frames during transmission is 72Bit */ + #define ETH_MACCR_IFG_64Bit ((unsigned int)0x00080000) /* Minimum IFG between frames during transmission is 64Bit */ + #define ETH_MACCR_IFG_56Bit ((unsigned int)0x000A0000) /* Minimum IFG between frames during transmission is 56Bit */ + #define ETH_MACCR_IFG_48Bit ((unsigned int)0x000C0000) /* Minimum IFG between frames during transmission is 48Bit */ + #define ETH_MACCR_IFG_40Bit ((unsigned int)0x000E0000) /* Minimum IFG between frames during transmission is 40Bit */ +#define ETH_MACCR_CSD ((unsigned int)0x00010000) /* Carrier sense disable (during transmission) */ +#define ETH_MACCR_FES ((unsigned int)0x00004000) /* Fast ethernet speed */ +#define ETH_MACCR_ROD ((unsigned int)0x00002000) /* Receive own disable */ +#define ETH_MACCR_LM ((unsigned int)0x00001000) /* loopback mode */ +#define ETH_MACCR_DM ((unsigned int)0x00000800) /* Duplex mode */ +#define ETH_MACCR_IPCO ((unsigned int)0x00000400) /* IP Checksum offload */ +#define ETH_MACCR_RD ((unsigned int)0x00000200) /* Retry disable */ +#define ETH_MACCR_APCS ((unsigned int)0x00000080) /* Automatic Pad/CRC stripping */ +#define ETH_MACCR_BL ((unsigned int)0x00000060) /* Back-off limit: random integer number (r) of slot time delays before reschedulinga transmission attempt during retries after a collision: 0 =< r <2^k */ + #define ETH_MACCR_BL_10 ((unsigned int)0x00000000) /* k = min (n, 10) */ + #define ETH_MACCR_BL_8 ((unsigned int)0x00000020) /* k = min (n, 8) */ + #define ETH_MACCR_BL_4 ((unsigned int)0x00000040) /* k = min (n, 4) */ + #define ETH_MACCR_BL_1 ((unsigned int)0x00000060) /* k = min (n, 1) */ +#define ETH_MACCR_DC ((unsigned int)0x00000010) /* Defferal check */ +#define ETH_MACCR_TE ((unsigned int)0x00000008) /* Transmitter enable */ +#define ETH_MACCR_RE ((unsigned int)0x00000004) /* Receiver enable */ + +#define ETH_MACFFR_RA ((unsigned int)0x80000000) /* Receive all */ +#define ETH_MACFFR_HPF ((unsigned int)0x00000400) /* Hash or perfect filter */ +#define ETH_MACFFR_SAF ((unsigned int)0x00000200) /* Source address filter enable */ +#define ETH_MACFFR_SAIF ((unsigned int)0x00000100) /* SA inverse filtering */ +#define ETH_MACFFR_PCF ((unsigned int)0x000000C0) /* Pass control frames: 3 cases */ + #define ETH_MACFFR_PCF_BlockAll ((unsigned int)0x00000040) /* MAC filters all control frames from reaching the application */ + #define ETH_MACFFR_PCF_ForwardAll ((unsigned int)0x00000080) /* MAC forwards all control frames to application even if they fail the Address Filter */ + #define ETH_MACFFR_PCF_ForwardPassedAddrFilter ((unsigned int)0x000000C0) /* MAC forwards control frames that pass the Address Filter. */ +#define ETH_MACFFR_BFD ((unsigned int)0x00000020) /* Broadcast frame disable */ +#define ETH_MACFFR_PAM ((unsigned int)0x00000010) /* Pass all mutlicast */ +#define ETH_MACFFR_DAIF ((unsigned int)0x00000008) /* DA Inverse filtering */ +#define ETH_MACFFR_HM ((unsigned int)0x00000004) /* Hash multicast */ +#define ETH_MACFFR_HU ((unsigned int)0x00000002) /* Hash unicast */ +#define ETH_MACFFR_PM ((unsigned int)0x00000001) /* Promiscuous mode */ + +#define ETH_MACHTHR_HTH ((unsigned int)0xFFFFFFFF) /* Hash table high */ +#define ETH_MACHTLR_HTL ((unsigned int)0xFFFFFFFF) /* Hash table low */ + +#define ETH_MACMIIAR_PA ((unsigned int)0x0000F800) /* Physical layer address */ +#define ETH_MACMIIAR_MR ((unsigned int)0x000007C0) /* MII register in the selected PHY */ +#define ETH_MACMIIAR_CR ((unsigned int)0x0000001C) /* CR clock range: 6 cases */ + #define ETH_MACMIIAR_CR_Div42 ((unsigned int)0x00000000) /* HCLK:60-100 MHz; MDC clock= HCLK/42 */ + #define ETH_MACMIIAR_CR_Div16 ((unsigned int)0x00000008) /* HCLK:20-35 MHz; MDC clock= HCLK/16 */ + #define ETH_MACMIIAR_CR_Div26 ((unsigned int)0x0000000C) /* HCLK:35-60 MHz; MDC clock= HCLK/26 */ +#define ETH_MACMIIAR_MW ((unsigned int)0x00000002) /* MII write */ +#define ETH_MACMIIAR_MB ((unsigned int)0x00000001) /* MII busy */ +#define ETH_MACMIIDR_MD ((unsigned int)0x0000FFFF) /* MII data: read/write data from/to PHY */ +#define ETH_MACFCR_PT ((unsigned int)0xFFFF0000) /* Pause time */ +#define ETH_MACFCR_ZQPD ((unsigned int)0x00000080) /* Zero-quanta pause disable */ +#define ETH_MACFCR_PLT ((unsigned int)0x00000030) /* Pause low threshold: 4 cases */ + #define ETH_MACFCR_PLT_Minus4 ((unsigned int)0x00000000) /* Pause time minus 4 slot times */ + #define ETH_MACFCR_PLT_Minus28 ((unsigned int)0x00000010) /* Pause time minus 28 slot times */ + #define ETH_MACFCR_PLT_Minus144 ((unsigned int)0x00000020) /* Pause time minus 144 slot times */ + #define ETH_MACFCR_PLT_Minus256 ((unsigned int)0x00000030) /* Pause time minus 256 slot times */ +#define ETH_MACFCR_UPFD ((unsigned int)0x00000008) /* Unicast pause frame detect */ +#define ETH_MACFCR_RFCE ((unsigned int)0x00000004) /* Receive flow control enable */ +#define ETH_MACFCR_TFCE ((unsigned int)0x00000002) /* Transmit flow control enable */ +#define ETH_MACFCR_FCBBPA ((unsigned int)0x00000001) /* Flow control busy/backpressure activate */ + +#define ETH_MACVLANTR_VLANTC ((unsigned int)0x00010000) /* 12-bit VLAN tag comparison */ +#define ETH_MACVLANTR_VLANTI ((unsigned int)0x0000FFFF) /* VLAN tag identifier (for receive frames) */ + +#define ETH_MACRWUFFR_D ((unsigned int)0xFFFFFFFF) /* Wake-up frame filter register data */ +/* Eight sequential Writes to this address (offset 0x28) will write all Wake-UpFrame Filter Registers. +Eight sequential Reads from this address (offset 0x28) will read all Wake-UpFrame Filter Registers. */ + +/* +Wake-UpFrame Filter Reg0 : Filter 0 Byte Mask +Wake-UpFrame Filter Reg1 : Filter 1 Byte Mask +Wake-UpFrame Filter Reg2 : Filter 2 Byte Mask +Wake-UpFrame Filter Reg3 : Filter 3 Byte Mask +Wake-UpFrame Filter Reg4 : RSVD - Filter3 Command - RSVD - Filter2 Command - + RSVD - Filter1 Command - RSVD - Filter0 Command +Wake-UpFrame Filter Re5 : Filter3 Offset - Filter2 Offset - Filter1 Offset - Filter0 Offset +Wake-UpFrame Filter Re6 : Filter1 CRC16 - Filter0 CRC16 +Wake-UpFrame Filter Re7 : Filter3 CRC16 - Filter2 CRC16 */ + +#define ETH_MACPMTCSR_WFFRPR ((unsigned int)0x80000000) /* Wake-Up Frame Filter Register Pointer Reset */ +#define ETH_MACPMTCSR_GU ((unsigned int)0x00000200) /* Global Unicast */ +#define ETH_MACPMTCSR_WFR ((unsigned int)0x00000040) /* Wake-Up Frame Received */ +#define ETH_MACPMTCSR_MPR ((unsigned int)0x00000020) /* Magic Packet Received */ +#define ETH_MACPMTCSR_WFE ((unsigned int)0x00000004) /* Wake-Up Frame Enable */ +#define ETH_MACPMTCSR_MPE ((unsigned int)0x00000002) /* Magic Packet Enable */ +#define ETH_MACPMTCSR_PD ((unsigned int)0x00000001) /* Power Down */ + +#define ETH_MACSR_TSTS ((unsigned int)0x00000200) /* Time stamp trigger status */ +#define ETH_MACSR_MMCTS ((unsigned int)0x00000040) /* MMC transmit status */ +#define ETH_MACSR_MMMCRS ((unsigned int)0x00000020) /* MMC receive status */ +#define ETH_MACSR_MMCS ((unsigned int)0x00000010) /* MMC status */ +#define ETH_MACSR_PMTS ((unsigned int)0x00000008) /* PMT status */ + +#define ETH_MACIMR_TSTIM ((unsigned int)0x00000200) /* Time stamp trigger interrupt mask */ +#define ETH_MACIMR_PMTIM ((unsigned int)0x00000008) /* PMT interrupt mask */ + +#define ETH_MACA0HR_MACA0H ((unsigned int)0x0000FFFF) /* MAC address0 high */ + +#define ETH_MACA0LR_MACA0L ((unsigned int)0xFFFFFFFF) /* MAC address0 low */ + +#define ETH_MACA1HR_AE ((unsigned int)0x80000000) /* Address enable */ +#define ETH_MACA1HR_SA ((unsigned int)0x40000000) /* Source address */ +#define ETH_MACA1HR_MBC ((unsigned int)0x3F000000) /* Mask byte control: bits to mask for comparison of the MAC Address bytes */ + #define ETH_MACA1HR_MBC_HBits15_8 ((unsigned int)0x20000000) /* Mask MAC Address high reg bits [15:8] */ + #define ETH_MACA1HR_MBC_HBits7_0 ((unsigned int)0x10000000) /* Mask MAC Address high reg bits [7:0] */ + #define ETH_MACA1HR_MBC_LBits31_24 ((unsigned int)0x08000000) /* Mask MAC Address low reg bits [31:24] */ + #define ETH_MACA1HR_MBC_LBits23_16 ((unsigned int)0x04000000) /* Mask MAC Address low reg bits [23:16] */ + #define ETH_MACA1HR_MBC_LBits15_8 ((unsigned int)0x02000000) /* Mask MAC Address low reg bits [15:8] */ + #define ETH_MACA1HR_MBC_LBits7_0 ((unsigned int)0x01000000) /* Mask MAC Address low reg bits [7:0] */ +#define ETH_MACA1HR_MACA1H ((unsigned int)0x0000FFFF) /* MAC address1 high */ + +#define ETH_MACA1LR_MACA1L ((unsigned int)0xFFFFFFFF) /* MAC address1 low */ + +#define ETH_MACA2HR_AE ((unsigned int)0x80000000) /* Address enable */ +#define ETH_MACA2HR_SA ((unsigned int)0x40000000) /* Source address */ +#define ETH_MACA2HR_MBC ((unsigned int)0x3F000000) /* Mask byte control */ + #define ETH_MACA2HR_MBC_HBits15_8 ((unsigned int)0x20000000) /* Mask MAC Address high reg bits [15:8] */ + #define ETH_MACA2HR_MBC_HBits7_0 ((unsigned int)0x10000000) /* Mask MAC Address high reg bits [7:0] */ + #define ETH_MACA2HR_MBC_LBits31_24 ((unsigned int)0x08000000) /* Mask MAC Address low reg bits [31:24] */ + #define ETH_MACA2HR_MBC_LBits23_16 ((unsigned int)0x04000000) /* Mask MAC Address low reg bits [23:16] */ + #define ETH_MACA2HR_MBC_LBits15_8 ((unsigned int)0x02000000) /* Mask MAC Address low reg bits [15:8] */ + #define ETH_MACA2HR_MBC_LBits7_0 ((unsigned int)0x01000000) /* Mask MAC Address low reg bits [70] */ + +#define ETH_MACA2HR_MACA2H ((unsigned int)0x0000FFFF) /* MAC address1 high */ +#define ETH_MACA2LR_MACA2L ((unsigned int)0xFFFFFFFF) /* MAC address2 low */ + +#define ETH_MACA3HR_AE ((unsigned int)0x80000000) /* Address enable */ +#define ETH_MACA3HR_SA ((unsigned int)0x40000000) /* Source address */ +#define ETH_MACA3HR_MBC ((unsigned int)0x3F000000) /* Mask byte control */ + #define ETH_MACA3HR_MBC_HBits15_8 ((unsigned int)0x20000000) /* Mask MAC Address high reg bits [15:8] */ + #define ETH_MACA3HR_MBC_HBits7_0 ((unsigned int)0x10000000) /* Mask MAC Address high reg bits [7:0] */ + #define ETH_MACA3HR_MBC_LBits31_24 ((unsigned int)0x08000000) /* Mask MAC Address low reg bits [31:24] */ + #define ETH_MACA3HR_MBC_LBits23_16 ((unsigned int)0x04000000) /* Mask MAC Address low reg bits [23:16] */ + #define ETH_MACA3HR_MBC_LBits15_8 ((unsigned int)0x02000000) /* Mask MAC Address low reg bits [15:8] */ + #define ETH_MACA3HR_MBC_LBits7_0 ((unsigned int)0x01000000) /* Mask MAC Address low reg bits [70] */ +#define ETH_MACA3HR_MACA3H ((unsigned int)0x0000FFFF) /* MAC address3 high */ +#define ETH_MACA3LR_MACA3L ((unsigned int)0xFFFFFFFF) /* MAC address3 low */ + +/******************************************************************************/ +/* +/* ETH MMC Register +/* +/******************************************************************************/ +#define ETH_MMCCR_MCFHP ((unsigned int)0x00000020) /* MMC counter Full-Half preset */ +#define ETH_MMCCR_MCP ((unsigned int)0x00000010) /* MMC counter preset */ +#define ETH_MMCCR_MCF ((unsigned int)0x00000008) /* MMC Counter Freeze */ +#define ETH_MMCCR_ROR ((unsigned int)0x00000004) /* Reset on Read */ +#define ETH_MMCCR_CSR ((unsigned int)0x00000002) /* Counter Stop Rollover */ +#define ETH_MMCCR_CR ((unsigned int)0x00000001) /* Counters Reset */ + +#define ETH_MMCRIR_RGUFS ((unsigned int)0x00020000) /* Set when Rx good unicast frames counter reaches half the maximum value */ +#define ETH_MMCRIR_RFAES ((unsigned int)0x00000040) /* Set when Rx alignment error counter reaches half the maximum value */ +#define ETH_MMCRIR_RFCES ((unsigned int)0x00000020) /* Set when Rx crc error counter reaches half the maximum value */ + +#define ETH_MMCTIR_TGFS ((unsigned int)0x00200000) /* Set when Tx good frame count counter reaches half the maximum value */ +#define ETH_MMCTIR_TGFMSCS ((unsigned int)0x00008000) /* Set when Tx good multi col counter reaches half the maximum value */ +#define ETH_MMCTIR_TGFSCS ((unsigned int)0x00004000) /* Set when Tx good single col counter reaches half the maximum value */ + +#define ETH_MMCRIMR_RGUFM ((unsigned int)0x00020000) /* Mask the interrupt when Rx good unicast frames counter reaches half the maximum value */ +#define ETH_MMCRIMR_RFAEM ((unsigned int)0x00000040) /* Mask the interrupt when when Rx alignment error counter reaches half the maximum value */ +#define ETH_MMCRIMR_RFCEM ((unsigned int)0x00000020) /* Mask the interrupt when Rx crc error counter reaches half the maximum value */ + +#define ETH_MMCTIMR_TGFM ((unsigned int)0x00200000) /* Mask the interrupt when Tx good frame count counter reaches half the maximum value */ +#define ETH_MMCTIMR_TGFMSCM ((unsigned int)0x00008000) /* Mask the interrupt when Tx good multi col counter reaches half the maximum value */ +#define ETH_MMCTIMR_TGFSCM ((unsigned int)0x00004000) /* Mask the interrupt when Tx good single col counter reaches half the maximum value */ + +#define ETH_MMCTGFSCCR_TGFSCC ((unsigned int)0xFFFFFFFF) /* Number of successfully transmitted frames after a single collision in Half-duplex mode. */ + +#define ETH_MMCTGFMSCCR_TGFMSCC ((unsigned int)0xFFFFFFFF) /* Number of successfully transmitted frames after more than a single collision in Half-duplex mode. */ + +#define ETH_MMCTGFCR_TGFC ((unsigned int)0xFFFFFFFF) /* Number of good frames transmitted. */ + +#define ETH_MMCRFCECR_RFCEC ((unsigned int)0xFFFFFFFF) /* Number of frames received with CRC error. */ + +#define ETH_MMCRFAECR_RFAEC ((unsigned int)0xFFFFFFFF) /* Number of frames received with alignment (dribble) error */ + +#define ETH_MMCRGUFCR_RGUFC ((unsigned int)0xFFFFFFFF) /* Number of good unicast frames received. */ + + +/******************************************************************************/ +/* +/* ETH Precise Clock Protocol Register +/* +/******************************************************************************/ +#define ETH_PTPTSCR_TSCNT ((unsigned int)0x00030000) /* Time stamp clock node type */ +#define ETH_PTPTSSR_TSSMRME ((unsigned int)0x00008000) /* Time stamp snapshot for message relevant to master enable */ +#define ETH_PTPTSSR_TSSEME ((unsigned int)0x00004000) /* Time stamp snapshot for event message enable */ +#define ETH_PTPTSSR_TSSIPV4FE ((unsigned int)0x00002000) /* Time stamp snapshot for IPv4 frames enable */ +#define ETH_PTPTSSR_TSSIPV6FE ((unsigned int)0x00001000) /* Time stamp snapshot for IPv6 frames enable */ +#define ETH_PTPTSSR_TSSPTPOEFE ((unsigned int)0x00000800) /* Time stamp snapshot for PTP over ethernet frames enable */ +#define ETH_PTPTSSR_TSPTPPSV2E ((unsigned int)0x00000400) /* Time stamp PTP packet snooping for version2 format enable */ +#define ETH_PTPTSSR_TSSSR ((unsigned int)0x00000200) /* Time stamp Sub-seconds rollover */ +#define ETH_PTPTSSR_TSSARFE ((unsigned int)0x00000100) /* Time stamp snapshot for all received frames enable */ + +#define ETH_PTPTSCR_TSARU ((unsigned int)0x00000020) /* Addend register update */ +#define ETH_PTPTSCR_TSITE ((unsigned int)0x00000010) /* Time stamp interrupt trigger enable */ +#define ETH_PTPTSCR_TSSTU ((unsigned int)0x00000008) /* Time stamp update */ +#define ETH_PTPTSCR_TSSTI ((unsigned int)0x00000004) /* Time stamp initialize */ +#define ETH_PTPTSCR_TSFCU ((unsigned int)0x00000002) /* Time stamp fine or coarse update */ +#define ETH_PTPTSCR_TSE ((unsigned int)0x00000001) /* Time stamp enable */ + +#define ETH_PTPSSIR_STSSI ((unsigned int)0x000000FF) /* System time Sub-second increment value */ + +#define ETH_PTPTSHR_STS ((unsigned int)0xFFFFFFFF) /* System Time second */ + +#define ETH_PTPTSLR_STPNS ((unsigned int)0x80000000) /* System Time Positive or negative time */ +#define ETH_PTPTSLR_STSS ((unsigned int)0x7FFFFFFF) /* System Time sub-seconds */ + +#define ETH_PTPTSHUR_TSUS ((unsigned int)0xFFFFFFFF) /* Time stamp update seconds */ + +#define ETH_PTPTSLUR_TSUPNS ((unsigned int)0x80000000) /* Time stamp update Positive or negative time */ +#define ETH_PTPTSLUR_TSUSS ((unsigned int)0x7FFFFFFF) /* Time stamp update sub-seconds */ + +#define ETH_PTPTSAR_TSA ((unsigned int)0xFFFFFFFF) /* Time stamp addend */ + +#define ETH_PTPTTHR_TTSH ((unsigned int)0xFFFFFFFF) /* Target time stamp high */ + +#define ETH_PTPTTLR_TTSL ((unsigned int)0xFFFFFFFF) /* Target time stamp low */ + +#define ETH_PTPTSSR_TSTTR ((unsigned int)0x00000020) /* Time stamp target time reached */ +#define ETH_PTPTSSR_TSSO ((unsigned int)0x00000010) /* Time stamp seconds overflow */ + +/******************************************************************************/ +/* +/* ETH DMA Register +/* +/******************************************************************************/ +#define ETH_DMABMR_AAB ((unsigned int)0x02000000) /* Address-Aligned beats */ +#define ETH_DMABMR_FPM ((unsigned int)0x01000000) /* 4xPBL mode */ +#define ETH_DMABMR_USP ((unsigned int)0x00800000) /* Use separate PBL */ +#define ETH_DMABMR_RDP ((unsigned int)0x007E0000) /* RxDMA PBL */ + #define ETH_DMABMR_RDP_1Beat ((unsigned int)0x00020000) /* maximum number of beats to be transferred in one RxDMA transaction is 1 */ + #define ETH_DMABMR_RDP_2Beat ((unsigned int)0x00040000) /* maximum number of beats to be transferred in one RxDMA transaction is 2 */ + #define ETH_DMABMR_RDP_4Beat ((unsigned int)0x00080000) /* maximum number of beats to be transferred in one RxDMA transaction is 4 */ + #define ETH_DMABMR_RDP_8Beat ((unsigned int)0x00100000) /* maximum number of beats to be transferred in one RxDMA transaction is 8 */ + #define ETH_DMABMR_RDP_16Beat ((unsigned int)0x00200000) /* maximum number of beats to be transferred in one RxDMA transaction is 16 */ + #define ETH_DMABMR_RDP_32Beat ((unsigned int)0x00400000) /* maximum number of beats to be transferred in one RxDMA transaction is 32 */ + #define ETH_DMABMR_RDP_4xPBL_4Beat ((unsigned int)0x01020000) /* maximum number of beats to be transferred in one RxDMA transaction is 4 */ + #define ETH_DMABMR_RDP_4xPBL_8Beat ((unsigned int)0x01040000) /* maximum number of beats to be transferred in one RxDMA transaction is 8 */ + #define ETH_DMABMR_RDP_4xPBL_16Beat ((unsigned int)0x01080000) /* maximum number of beats to be transferred in one RxDMA transaction is 16 */ + #define ETH_DMABMR_RDP_4xPBL_32Beat ((unsigned int)0x01100000) /* maximum number of beats to be transferred in one RxDMA transaction is 32 */ + #define ETH_DMABMR_RDP_4xPBL_64Beat ((unsigned int)0x01200000) /* maximum number of beats to be transferred in one RxDMA transaction is 64 */ + #define ETH_DMABMR_RDP_4xPBL_128Beat ((unsigned int)0x01400000) /* maximum number of beats to be transferred in one RxDMA transaction is 128 */ +#define ETH_DMABMR_FB ((unsigned int)0x00010000) /* Fixed Burst */ +#define ETH_DMABMR_RTPR ((unsigned int)0x0000C000) /* Rx Tx priority ratio */ + #define ETH_DMABMR_RTPR_1_1 ((unsigned int)0x00000000) /* Rx Tx priority ratio */ + #define ETH_DMABMR_RTPR_2_1 ((unsigned int)0x00004000) /* Rx Tx priority ratio */ + #define ETH_DMABMR_RTPR_3_1 ((unsigned int)0x00008000) /* Rx Tx priority ratio */ + #define ETH_DMABMR_RTPR_4_1 ((unsigned int)0x0000C000) /* Rx Tx priority ratio */ +#define ETH_DMABMR_PBL ((unsigned int)0x00003F00) /* Programmable burst length */ + #define ETH_DMABMR_PBL_1Beat ((unsigned int)0x00000100) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 1 */ + #define ETH_DMABMR_PBL_2Beat ((unsigned int)0x00000200) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 2 */ + #define ETH_DMABMR_PBL_4Beat ((unsigned int)0x00000400) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ + #define ETH_DMABMR_PBL_8Beat ((unsigned int)0x00000800) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ + #define ETH_DMABMR_PBL_16Beat ((unsigned int)0x00001000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ + #define ETH_DMABMR_PBL_32Beat ((unsigned int)0x00002000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ + #define ETH_DMABMR_PBL_4xPBL_4Beat ((unsigned int)0x01000100) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 4 */ + #define ETH_DMABMR_PBL_4xPBL_8Beat ((unsigned int)0x01000200) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 8 */ + #define ETH_DMABMR_PBL_4xPBL_16Beat ((unsigned int)0x01000400) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 16 */ + #define ETH_DMABMR_PBL_4xPBL_32Beat ((unsigned int)0x01000800) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 32 */ + #define ETH_DMABMR_PBL_4xPBL_64Beat ((unsigned int)0x01001000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 64 */ + #define ETH_DMABMR_PBL_4xPBL_128Beat ((unsigned int)0x01002000) /* maximum number of beats to be transferred in one TxDMA (or both) transaction is 128 */ +#define ETH_DMABMR_EDE ((unsigned int)0x00000080) /* Enhanced Descriptor Enable */ +#define ETH_DMABMR_DSL ((unsigned int)0x0000007C) /* Descriptor Skip Length */ +#define ETH_DMABMR_DA ((unsigned int)0x00000002) /* DMA arbitration scheme */ +#define ETH_DMABMR_SR ((unsigned int)0x00000001) /* Software reset */ + +#define ETH_DMATPDR_TPD ((unsigned int)0xFFFFFFFF) /* Transmit poll demand */ + +#define ETH_DMARPDR_RPD ((unsigned int)0xFFFFFFFF) /* Receive poll demand */ + +#define ETH_DMARDLAR_SRL ((unsigned int)0xFFFFFFFF) /* Start of receive list */ + +#define ETH_DMATDLAR_STL ((unsigned int)0xFFFFFFFF) /* Start of transmit list */ + +#define ETH_DMASR_TSTS ((unsigned int)0x20000000) /* Time-stamp trigger status */ +#define ETH_DMASR_PMTS ((unsigned int)0x10000000) /* PMT status */ +#define ETH_DMASR_MMCS ((unsigned int)0x08000000) /* MMC status */ +#define ETH_DMASR_EBS ((unsigned int)0x03800000) /* Error bits status */ + #define ETH_DMASR_EBS_DescAccess ((unsigned int)0x02000000) /* Error bits 0-data buffer, 1-desc. access */ + #define ETH_DMASR_EBS_ReadTransf ((unsigned int)0x01000000) /* Error bits 0-write trnsf, 1-read transfr */ + #define ETH_DMASR_EBS_DataTransfTx ((unsigned int)0x00800000) /* Error bits 0-Rx DMA, 1-Tx DMA */ +#define ETH_DMASR_TPS ((unsigned int)0x00700000) /* Transmit process state */ + #define ETH_DMASR_TPS_Stopped ((unsigned int)0x00000000) /* Stopped - Reset or Stop Tx Command issued */ + #define ETH_DMASR_TPS_Fetching ((unsigned int)0x00100000) /* Running - fetching the Tx descriptor */ + #define ETH_DMASR_TPS_Waiting ((unsigned int)0x00200000) /* Running - waiting for status */ + #define ETH_DMASR_TPS_Reading ((unsigned int)0x00300000) /* Running - reading the data from host memory */ + #define ETH_DMASR_TPS_Suspended ((unsigned int)0x00600000) /* Suspended - Tx Descriptor unavailabe */ + #define ETH_DMASR_TPS_Closing ((unsigned int)0x00700000) /* Running - closing Rx descriptor */ +#define ETH_DMASR_RPS ((unsigned int)0x000E0000) /* Receive process state */ + #define ETH_DMASR_RPS_Stopped ((unsigned int)0x00000000) /* Stopped - Reset or Stop Rx Command issued */ + #define ETH_DMASR_RPS_Fetching ((unsigned int)0x00020000) /* Running - fetching the Rx descriptor */ + #define ETH_DMASR_RPS_Waiting ((unsigned int)0x00060000) /* Running - waiting for packet */ + #define ETH_DMASR_RPS_Suspended ((unsigned int)0x00080000) /* Suspended - Rx Descriptor unavailable */ + #define ETH_DMASR_RPS_Closing ((unsigned int)0x000A0000) /* Running - closing descriptor */ + #define ETH_DMASR_RPS_Queuing ((unsigned int)0x000E0000) /* Running - queuing the recieve frame into host memory */ +#define ETH_DMASR_NIS ((unsigned int)0x00010000) /* Normal interrupt summary */ +#define ETH_DMASR_AIS ((unsigned int)0x00008000) /* Abnormal interrupt summary */ +#define ETH_DMASR_ERS ((unsigned int)0x00004000) /* Early receive status */ +#define ETH_DMASR_FBES ((unsigned int)0x00002000) /* Fatal bus error status */ +#define ETH_DMASR_ETS ((unsigned int)0x00000400) /* Early transmit status */ +#define ETH_DMASR_RWTS ((unsigned int)0x00000200) /* Receive watchdog timeout status */ +#define ETH_DMASR_RPSS ((unsigned int)0x00000100) /* Receive process stopped status */ +#define ETH_DMASR_RBUS ((unsigned int)0x00000080) /* Receive buffer unavailable status */ +#define ETH_DMASR_RS ((unsigned int)0x00000040) /* Receive status */ +#define ETH_DMASR_TUS ((unsigned int)0x00000020) /* Transmit underflow status */ +#define ETH_DMASR_ROS ((unsigned int)0x00000010) /* Receive overflow status */ +#define ETH_DMASR_TJTS ((unsigned int)0x00000008) /* Transmit jabber timeout status */ +#define ETH_DMASR_TBUS ((unsigned int)0x00000004) /* Transmit buffer unavailable status */ +#define ETH_DMASR_TPSS ((unsigned int)0x00000002) /* Transmit process stopped status */ +#define ETH_DMASR_TS ((unsigned int)0x00000001) /* Transmit status */ + +#define ETH_DMAOMR_DTCEFD ((unsigned int)0x04000000) /* Disable Dropping of TCP/IP checksum error frames */ +#define ETH_DMAOMR_RSF ((unsigned int)0x02000000) /* Receive store and forward */ +#define ETH_DMAOMR_DFRF ((unsigned int)0x01000000) /* Disable flushing of received frames */ +#define ETH_DMAOMR_TSF ((unsigned int)0x00200000) /* Transmit store and forward */ +#define ETH_DMAOMR_FTF ((unsigned int)0x00100000) /* Flush transmit FIFO */ +#define ETH_DMAOMR_TTC ((unsigned int)0x0001C000) /* Transmit threshold control */ + #define ETH_DMAOMR_TTC_64Bytes ((unsigned int)0x00000000) /* threshold level of the MTL Transmit FIFO is 64 Bytes */ + #define ETH_DMAOMR_TTC_128Bytes ((unsigned int)0x00004000) /* threshold level of the MTL Transmit FIFO is 128 Bytes */ + #define ETH_DMAOMR_TTC_192Bytes ((unsigned int)0x00008000) /* threshold level of the MTL Transmit FIFO is 192 Bytes */ + #define ETH_DMAOMR_TTC_256Bytes ((unsigned int)0x0000C000) /* threshold level of the MTL Transmit FIFO is 256 Bytes */ + #define ETH_DMAOMR_TTC_40Bytes ((unsigned int)0x00010000) /* threshold level of the MTL Transmit FIFO is 40 Bytes */ + #define ETH_DMAOMR_TTC_32Bytes ((unsigned int)0x00014000) /* threshold level of the MTL Transmit FIFO is 32 Bytes */ + #define ETH_DMAOMR_TTC_24Bytes ((unsigned int)0x00018000) /* threshold level of the MTL Transmit FIFO is 24 Bytes */ + #define ETH_DMAOMR_TTC_16Bytes ((unsigned int)0x0001C000) /* threshold level of the MTL Transmit FIFO is 16 Bytes */ +#define ETH_DMAOMR_ST ((unsigned int)0x00002000) /* Start/stop transmission command */ +#define ETH_DMAOMR_FEF ((unsigned int)0x00000080) /* Forward error frames */ +#define ETH_DMAOMR_FUGF ((unsigned int)0x00000040) /* Forward undersized good frames */ +#define ETH_DMAOMR_RTC ((unsigned int)0x00000018) /* receive threshold control */ + #define ETH_DMAOMR_RTC_64Bytes ((unsigned int)0x00000000) /* threshold level of the MTL Receive FIFO is 64 Bytes */ + #define ETH_DMAOMR_RTC_32Bytes ((unsigned int)0x00000008) /* threshold level of the MTL Receive FIFO is 32 Bytes */ + #define ETH_DMAOMR_RTC_96Bytes ((unsigned int)0x00000010) /* threshold level of the MTL Receive FIFO is 96 Bytes */ + #define ETH_DMAOMR_RTC_128Bytes ((unsigned int)0x00000018) /* threshold level of the MTL Receive FIFO is 128 Bytes */ +#define ETH_DMAOMR_OSF ((unsigned int)0x00000004) /* operate on second frame */ +#define ETH_DMAOMR_SR ((unsigned int)0x00000002) /* Start/stop receive */ + +#define ETH_DMAIER_NISE ((unsigned int)0x00010000) /* Normal interrupt summary enable */ +#define ETH_DMAIER_AISE ((unsigned int)0x00008000) /* Abnormal interrupt summary enable */ +#define ETH_DMAIER_ERIE ((unsigned int)0x00004000) /* Early receive interrupt enable */ +#define ETH_DMAIER_FBEIE ((unsigned int)0x00002000) /* Fatal bus error interrupt enable */ +#define ETH_DMAIER_ETIE ((unsigned int)0x00000400) /* Early transmit interrupt enable */ +#define ETH_DMAIER_RWTIE ((unsigned int)0x00000200) /* Receive watchdog timeout interrupt enable */ +#define ETH_DMAIER_RPSIE ((unsigned int)0x00000100) /* Receive process stopped interrupt enable */ +#define ETH_DMAIER_RBUIE ((unsigned int)0x00000080) /* Receive buffer unavailable interrupt enable */ +#define ETH_DMAIER_RIE ((unsigned int)0x00000040) /* Receive interrupt enable */ +#define ETH_DMAIER_TUIE ((unsigned int)0x00000020) /* Transmit Underflow interrupt enable */ +#define ETH_DMAIER_ROIE ((unsigned int)0x00000010) /* Receive Overflow interrupt enable */ +#define ETH_DMAIER_TJTIE ((unsigned int)0x00000008) /* Transmit jabber timeout interrupt enable */ +#define ETH_DMAIER_TBUIE ((unsigned int)0x00000004) /* Transmit buffer unavailable interrupt enable */ +#define ETH_DMAIER_TPSIE ((unsigned int)0x00000002) /* Transmit process stopped interrupt enable */ +#define ETH_DMAIER_TIE ((unsigned int)0x00000001) /* Transmit interrupt enable */ + +#define ETH_DMAMFBOCR_OFOC ((unsigned int)0x10000000) /* Overflow bit for FIFO overflow counter */ +#define ETH_DMAMFBOCR_MFA ((unsigned int)0x0FFE0000) /* Number of frames missed by the application */ +#define ETH_DMAMFBOCR_OMFC ((unsigned int)0x00010000) /* Overflow bit for missed frame counter */ +#define ETH_DMAMFBOCR_MFC ((unsigned int)0x0000FFFF) /* Number of frames missed by the controller */ + +#define ETH_DMACHTDR_HTDAP ((unsigned int)0xFFFFFFFF) /* Host transmit descriptor address pointer */ +#define ETH_DMACHRDR_HRDAP ((unsigned int)0xFFFFFFFF) /* Host receive descriptor address pointer */ +#define ETH_DMACHTBAR_HTBAP ((unsigned int)0xFFFFFFFF) /* Host transmit buffer address pointer */ +#define ETH_DMACHRBAR_HRBAP ((unsigned int)0xFFFFFFFF) /* Host receive buffer address pointer */ + + +#define ETH_MAC_ADDR_HBASE (ETH_MAC_BASE + 0x40) /* ETHERNET MAC address high offset */ +#define ETH_MAC_ADDR_LBASE (ETH_MAC_BASE + 0x44) /* ETHERNET MAC address low offset */ + +/* ETHERNET MACMIIAR register Mask */ +#define MACMIIAR_CR_MASK ((uint32_t)0xFFFFFFE3) + +/* ETHERNET MACCR register Mask */ +#define MACCR_CLEAR_MASK ((uint32_t)0xFF20810F) + +/* ETHERNET MACFCR register Mask */ +#define MACFCR_CLEAR_MASK ((uint32_t)0x0000FF41) + +/* ETHERNET DMAOMR register Mask */ +#define DMAOMR_CLEAR_MASK ((uint32_t)0xF8DE3F23) + +/* ETHERNET Remote Wake-up frame register length */ +#define ETH_WAKEUP_REGISTER_LENGTH 8 + +/* ETHERNET Missed frames counter Shift */ +#define ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTERSHIFT 17 + +/* ETHERNET DMA Tx descriptors Collision Count Shift */ +#define ETH_DMATXDESC_COLLISION_COUNTSHIFT 3 + +/* ETHERNET DMA Tx descriptors Buffer2 Size Shift */ +#define ETH_DMATXDESC_BUFFER2_SIZESHIFT 16 + +/* ETHERNET DMA Rx descriptors Frame Length Shift */ +#define ETH_DMARXDESC_FRAME_LENGTHSHIFT 16 + +/* ETHERNET DMA Rx descriptors Buffer2 Size Shift */ +#define ETH_DMARXDESC_BUFFER2_SIZESHIFT 16 + +/* ETHERNET errors */ +#define ETH_ERROR ((uint32_t)0) +#define ETH_SUCCESS ((uint32_t)1) + + +void ETH_DeInit(void); +void ETH_StructInit(ETH_InitTypeDef* ETH_InitStruct); +void ETH_SoftwareReset(void); +FlagStatus ETH_GetSoftwareResetStatus(void); +FlagStatus ETH_GetlinkStaus (void); +void ETH_Start(void); +uint32_t ETH_HandleTxPkt(uint8_t *ppkt, uint16_t FrameLength); +void delay_clk (uint32_t nCount); +void printf_dmasr (void); +void print_dmasr_tbus(void); +void print_dmasr_rps(void); +void print_dmasr_tps(void); +uint32_t ETH_HandleRxPkt(uint8_t *ppkt); +uint32_t ETH_GetRxPktSize(void); +void ETH_DropRxPkt(void); +uint16_t ETH_ReadPHYRegister(uint16_t PHYAddress, uint16_t PHYReg); +uint32_t ETH_WritePHYRegister(uint16_t PHYAddress, uint16_t PHYReg, uint16_t PHYValue); +uint32_t ETH_PHYLoopBackCmd(uint16_t PHYAddress, FunctionalState NewState); + +void ETH_MACTransmissionCmd(FunctionalState NewState); +void ETH_MACReceptionCmd(FunctionalState NewState); +FlagStatus ETH_GetFlowControlBusyStatus(void); +void ETH_InitiatePauseControlFrame(void); +void ETH_BackPressureActivationCmd(FunctionalState NewState); +FlagStatus ETH_GetMACFlagStatus(uint32_t ETH_MAC_FLAG); +ITStatus ETH_GetMACITStatus(uint32_t ETH_MAC_IT); +void ETH_MACITConfig(uint32_t ETH_MAC_IT, FunctionalState NewState); +void ETH_MACAddressConfig(uint32_t MacAddr, uint8_t *Addr); +void ETH_GetMACAddress(uint32_t MacAddr, uint8_t *Addr); +void ETH_MACAddressPerfectFilterCmd(uint32_t MacAddr, FunctionalState NewState); +void ETH_MACAddressFilterConfig(uint32_t MacAddr, uint32_t Filter); +void ETH_MACAddressMaskBytesFilterConfig(uint32_t MacAddr, uint32_t MaskByte); + +void ETH_DMATxDescChainInit(ETH_DMADESCTypeDef *DMATxDescTab, uint8_t *TxBuff, uint32_t TxBuffCount); +void ETH_DMATxDescRingInit(ETH_DMADESCTypeDef *DMATxDescTab, uint8_t *TxBuff1, uint8_t *TxBuff2, uint32_t TxBuffCount); +FlagStatus ETH_GetDMATxDescFlagStatus(ETH_DMADESCTypeDef *DMATxDesc, uint32_t ETH_DMATxDescFlag); +uint32_t ETH_GetDMATxDescCollisionCount(ETH_DMADESCTypeDef *DMATxDesc); +void ETH_SetDMATxDescOwnBit(ETH_DMADESCTypeDef *DMATxDesc); +void ETH_DMATxDescTransmitITConfig(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState); +void ETH_DMATxDescFrameSegmentConfig(ETH_DMADESCTypeDef *DMATxDesc, uint32_t DMATxDesc_FrameSegment); +void ETH_DMATxDescChecksumInsertionConfig(ETH_DMADESCTypeDef *DMATxDesc, uint32_t DMATxDesc_Checksum); +void ETH_DMATxDescCRCCmd(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState); +void ETH_DMATxDescEndOfRingCmd(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState); +void ETH_DMATxDescSecondAddressChainedCmd(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState); +void ETH_DMATxDescShortFramePaddingCmd(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState); +void ETH_DMATxDescTimeStampCmd(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState); +void ETH_DMATxDescBufferSizeConfig(ETH_DMADESCTypeDef *DMATxDesc, uint32_t BufferSize1, uint32_t BufferSize2); +void ETH_DMARxDescChainInit(ETH_DMADESCTypeDef *DMARxDescTab, uint8_t *RxBuff, uint32_t RxBuffCount); +void ETH_DMARxDescRingInit(ETH_DMADESCTypeDef *DMARxDescTab, uint8_t *RxBuff1, uint8_t *RxBuff2, uint32_t RxBuffCount); +FlagStatus ETH_GetDMARxDescFlagStatus(ETH_DMADESCTypeDef *DMARxDesc, uint32_t ETH_DMARxDescFlag); +void ETH_SetDMARxDescOwnBit(ETH_DMADESCTypeDef *DMARxDesc); +uint32_t ETH_GetDMARxDescFrameLength(ETH_DMADESCTypeDef *DMARxDesc); +void ETH_DMARxDescReceiveITConfig(ETH_DMADESCTypeDef *DMARxDesc, FunctionalState NewState); +void ETH_DMARxDescEndOfRingCmd(ETH_DMADESCTypeDef *DMARxDesc, FunctionalState NewState); +void ETH_DMARxDescSecondAddressChainedCmd(ETH_DMADESCTypeDef *DMARxDesc, FunctionalState NewState); +uint32_t ETH_GetDMARxDescBufferSize(ETH_DMADESCTypeDef *DMARxDesc, uint32_t DMARxDesc_Buffer); + +FlagStatus ETH_GetDMAFlagStatus(uint32_t ETH_DMA_FLAG); +void ETH_DMAClearFlag(uint32_t ETH_DMA_FLAG); +ITStatus ETH_GetDMAITStatus(uint32_t ETH_DMA_IT); +void ETH_DMAClearITPendingBit(uint32_t ETH_DMA_IT); +uint32_t ETH_GetTransmitProcessState(void); +uint32_t ETH_GetReceiveProcessState(void); +void ETH_FlushTransmitFIFO(void); +FlagStatus ETH_GetFlushTransmitFIFOStatus(void); +void ETH_DMATransmissionCmd(FunctionalState NewState); +void ETH_DMAReceptionCmd(FunctionalState NewState); +void ETH_DMAITConfig(uint32_t ETH_DMA_IT, FunctionalState NewState); +FlagStatus ETH_GetDMAOverflowStatus(uint32_t ETH_DMA_Overflow); +uint32_t ETH_GetRxOverflowMissedFrameCounter(void); +uint32_t ETH_GetBufferUnavailableMissedFrameCounter(void); +uint32_t ETH_GetCurrentTxDescStartAddress(void); +uint32_t ETH_GetCurrentRxDescStartAddress(void); +uint32_t ETH_GetCurrentTxBufferAddress(void); +uint32_t ETH_GetCurrentRxBufferAddress(void); +void ETH_ResumeDMATransmission(void); +void ETH_ResumeDMAReception(void); + +void ETH_ResetWakeUpFrameFilterRegisterPointer(void); +void ETH_SetWakeUpFrameFilterRegister(uint32_t *Buffer); +void ETH_GlobalUnicastWakeUpCmd(FunctionalState NewState); +FlagStatus ETH_GetPMTFlagStatus(uint32_t ETH_PMT_FLAG); +void ETH_WakeUpFrameDetectionCmd(FunctionalState NewState); +void ETH_MagicPacketDetectionCmd(FunctionalState NewState); +void ETH_PowerDownCmd(FunctionalState NewState); + +void ETH_MMCCounterFreezeCmd(FunctionalState NewState); +void ETH_MMCResetOnReadCmd(FunctionalState NewState); +void ETH_MMCCounterRolloverCmd(FunctionalState NewState); +void ETH_MMCCountersReset(void); +void ETH_MMCITConfig(uint32_t ETH_MMC_IT, FunctionalState NewState); +ITStatus ETH_GetMMCITStatus(uint32_t ETH_MMC_IT); +uint32_t ETH_GetMMCRegister(uint32_t ETH_MMCReg); + +uint32_t ETH_HandlePTPTxPkt(uint8_t *ppkt, uint16_t FrameLength, uint32_t *PTPTxTab); +uint32_t ETH_HandlePTPRxPkt(uint8_t *ppkt, uint32_t *PTPRxTab); +void ETH_DMAPTPTxDescChainInit(ETH_DMADESCTypeDef *DMATxDescTab, ETH_DMADESCTypeDef *DMAPTPTxDescTab, uint8_t* TxBuff, uint32_t TxBuffCount); +void ETH_DMAPTPRxDescChainInit(ETH_DMADESCTypeDef *DMARxDescTab, ETH_DMADESCTypeDef *DMAPTPRxDescTab, uint8_t *RxBuff, uint32_t RxBuffCount); +void ETH_EnablePTPTimeStampAddend(void); +void ETH_EnablePTPTimeStampInterruptTrigger(void); +void ETH_EnablePTPTimeStampUpdate(void); +void ETH_InitializePTPTimeStamp(void); +void ETH_PTPUpdateMethodConfig(uint32_t UpdateMethod); +void ETH_PTPTimeStampCmd(FunctionalState NewState); +FlagStatus ETH_GetPTPFlagStatus(uint32_t ETH_PTP_FLAG); +void ETH_SetPTPSubSecondIncrement(uint32_t SubSecondValue); +void ETH_SetPTPTimeStampUpdate(uint32_t Sign, uint32_t SecondValue, uint32_t SubSecondValue); +void ETH_SetPTPTimeStampAddend(uint32_t Value); +void ETH_SetPTPTargetTime(uint32_t HighValue, uint32_t LowValue); +uint32_t ETH_GetPTPRegister(uint32_t ETH_PTPReg); +void RGMII_TXC_Delay(uint8_t clock_polarity,uint8_t delay_time); + + + +#endif + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_exti.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_exti.h new file mode 100644 index 00000000..361a3454 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_exti.h @@ -0,0 +1,88 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_exti.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* EXTI firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_EXTI_H +#define __CH32V30x_EXTI_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* EXTI mode enumeration */ +typedef enum +{ + EXTI_Mode_Interrupt = 0x00, + EXTI_Mode_Event = 0x04 +}EXTIMode_TypeDef; + +/* EXTI Trigger enumeration */ +typedef enum +{ + EXTI_Trigger_Rising = 0x08, + EXTI_Trigger_Falling = 0x0C, + EXTI_Trigger_Rising_Falling = 0x10 +}EXTITrigger_TypeDef; + +/* EXTI Init Structure definition */ +typedef struct +{ + uint32_t EXTI_Line; /* Specifies the EXTI lines to be enabled or disabled. + This parameter can be any combination of @ref EXTI_Lines */ + + EXTIMode_TypeDef EXTI_Mode; /* Specifies the mode for the EXTI lines. + This parameter can be a value of @ref EXTIMode_TypeDef */ + + EXTITrigger_TypeDef EXTI_Trigger; /* Specifies the trigger signal active edge for the EXTI lines. + This parameter can be a value of @ref EXTIMode_TypeDef */ + + FunctionalState EXTI_LineCmd; /* Specifies the new state of the selected EXTI lines. + This parameter can be set either to ENABLE or DISABLE */ +}EXTI_InitTypeDef; + + +/* EXTI_Lines */ +#define EXTI_Line0 ((uint32_t)0x00001) /* External interrupt line 0 */ +#define EXTI_Line1 ((uint32_t)0x00002) /* External interrupt line 1 */ +#define EXTI_Line2 ((uint32_t)0x00004) /* External interrupt line 2 */ +#define EXTI_Line3 ((uint32_t)0x00008) /* External interrupt line 3 */ +#define EXTI_Line4 ((uint32_t)0x00010) /* External interrupt line 4 */ +#define EXTI_Line5 ((uint32_t)0x00020) /* External interrupt line 5 */ +#define EXTI_Line6 ((uint32_t)0x00040) /* External interrupt line 6 */ +#define EXTI_Line7 ((uint32_t)0x00080) /* External interrupt line 7 */ +#define EXTI_Line8 ((uint32_t)0x00100) /* External interrupt line 8 */ +#define EXTI_Line9 ((uint32_t)0x00200) /* External interrupt line 9 */ +#define EXTI_Line10 ((uint32_t)0x00400) /* External interrupt line 10 */ +#define EXTI_Line11 ((uint32_t)0x00800) /* External interrupt line 11 */ +#define EXTI_Line12 ((uint32_t)0x01000) /* External interrupt line 12 */ +#define EXTI_Line13 ((uint32_t)0x02000) /* External interrupt line 13 */ +#define EXTI_Line14 ((uint32_t)0x04000) /* External interrupt line 14 */ +#define EXTI_Line15 ((uint32_t)0x08000) /* External interrupt line 15 */ +#define EXTI_Line16 ((uint32_t)0x10000) /* External interrupt line 16 Connected to the PVD Output */ +#define EXTI_Line17 ((uint32_t)0x20000) /* External interrupt line 17 Connected to the RTC Alarm event */ +#define EXTI_Line18 ((uint32_t)0x40000) /* External interrupt line 18 Connected to the USB Device/USB OTG FS + Wakeup from suspend event */ +#define EXTI_Line19 ((uint32_t)0x80000) /* External interrupt line 19 Connected to the Ethernet Wakeup event */ +#define EXTI_Line20 ((uint32_t)0x100000) /* External interrupt line 20 Connected to the USBHD Wakeup event */ + +void EXTI_DeInit(void); +void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct); +void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct); +void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line); +FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line); +void EXTI_ClearFlag(uint32_t EXTI_Line); +ITStatus EXTI_GetITStatus(uint32_t EXTI_Line); +void EXTI_ClearITPendingBit(uint32_t EXTI_Line); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_flash.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_flash.h new file mode 100644 index 00000000..6796b162 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_flash.h @@ -0,0 +1,157 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_flash.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the FLASH +* firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_FLASH_H +#define __CH32V30x_FLASH_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* FLASH Status */ +typedef enum +{ + FLASH_BUSY = 1, + FLASH_ERROR_PG, + FLASH_ERROR_WRP, + FLASH_COMPLETE, + FLASH_TIMEOUT +}FLASH_Status; + + +/* Flash_Latency */ +#define FLASH_Latency_0 ((uint32_t)0x00000000) /* FLASH Zero Latency cycle */ +#define FLASH_Latency_1 ((uint32_t)0x00000001) /* FLASH One Latency cycle */ +#define FLASH_Latency_2 ((uint32_t)0x00000002) /* FLASH Two Latency cycles */ + +/* Half_Cycle_Enable_Disable */ +#define FLASH_HalfCycleAccess_Enable ((uint32_t)0x00000008) /* FLASH Half Cycle Enable */ +#define FLASH_HalfCycleAccess_Disable ((uint32_t)0x00000000) /* FLASH Half Cycle Disable */ + +/* Prefetch_Buffer_Enable_Disable */ +#define FLASH_PrefetchBuffer_Enable ((uint32_t)0x00000010) /* FLASH Prefetch Buffer Enable */ +#define FLASH_PrefetchBuffer_Disable ((uint32_t)0x00000000) /* FLASH Prefetch Buffer Disable */ + +/* Values to be used with Low and Medium density devices */ +#define FLASH_WRProt_Pages0to3 ((uint32_t)0x00000001) /* CH32 Low and Medium density devices: Write protection of page 0 to 3 */ +#define FLASH_WRProt_Pages4to7 ((uint32_t)0x00000002) /* CH32 Low and Medium density devices: Write protection of page 4 to 7 */ +#define FLASH_WRProt_Pages8to11 ((uint32_t)0x00000004) /* CH32 Low and Medium density devices: Write protection of page 8 to 11 */ +#define FLASH_WRProt_Pages12to15 ((uint32_t)0x00000008) /* CH32 Low and Medium density devices: Write protection of page 12 to 15 */ +#define FLASH_WRProt_Pages16to19 ((uint32_t)0x00000010) /* CH32 Low and Medium density devices: Write protection of page 16 to 19 */ +#define FLASH_WRProt_Pages20to23 ((uint32_t)0x00000020) /* CH32 Low and Medium density devices: Write protection of page 20 to 23 */ +#define FLASH_WRProt_Pages24to27 ((uint32_t)0x00000040) /* CH32 Low and Medium density devices: Write protection of page 24 to 27 */ +#define FLASH_WRProt_Pages28to31 ((uint32_t)0x00000080) /* CH32 Low and Medium density devices: Write protection of page 28 to 31 */ + +/* Values to be used with Medium-density devices */ +#define FLASH_WRProt_Pages32to35 ((uint32_t)0x00000100) /* CH32 Medium-density devices: Write protection of page 32 to 35 */ +#define FLASH_WRProt_Pages36to39 ((uint32_t)0x00000200) /* CH32 Medium-density devices: Write protection of page 36 to 39 */ +#define FLASH_WRProt_Pages40to43 ((uint32_t)0x00000400) /* CH32 Medium-density devices: Write protection of page 40 to 43 */ +#define FLASH_WRProt_Pages44to47 ((uint32_t)0x00000800) /* CH32 Medium-density devices: Write protection of page 44 to 47 */ +#define FLASH_WRProt_Pages48to51 ((uint32_t)0x00001000) /* CH32 Medium-density devices: Write protection of page 48 to 51 */ +#define FLASH_WRProt_Pages52to55 ((uint32_t)0x00002000) /* CH32 Medium-density devices: Write protection of page 52 to 55 */ +#define FLASH_WRProt_Pages56to59 ((uint32_t)0x00004000) /* CH32 Medium-density devices: Write protection of page 56 to 59 */ +#define FLASH_WRProt_Pages60to63 ((uint32_t)0x00008000) /* CH32 Medium-density devices: Write protection of page 60 to 63 */ +#define FLASH_WRProt_Pages64to67 ((uint32_t)0x00010000) /* CH32 Medium-density devices: Write protection of page 64 to 67 */ +#define FLASH_WRProt_Pages68to71 ((uint32_t)0x00020000) /* CH32 Medium-density devices: Write protection of page 68 to 71 */ +#define FLASH_WRProt_Pages72to75 ((uint32_t)0x00040000) /* CH32 Medium-density devices: Write protection of page 72 to 75 */ +#define FLASH_WRProt_Pages76to79 ((uint32_t)0x00080000) /* CH32 Medium-density devices: Write protection of page 76 to 79 */ +#define FLASH_WRProt_Pages80to83 ((uint32_t)0x00100000) /* CH32 Medium-density devices: Write protection of page 80 to 83 */ +#define FLASH_WRProt_Pages84to87 ((uint32_t)0x00200000) /* CH32 Medium-density devices: Write protection of page 84 to 87 */ +#define FLASH_WRProt_Pages88to91 ((uint32_t)0x00400000) /* CH32 Medium-density devices: Write protection of page 88 to 91 */ +#define FLASH_WRProt_Pages92to95 ((uint32_t)0x00800000) /* CH32 Medium-density devices: Write protection of page 92 to 95 */ +#define FLASH_WRProt_Pages96to99 ((uint32_t)0x01000000) /* CH32 Medium-density devices: Write protection of page 96 to 99 */ +#define FLASH_WRProt_Pages100to103 ((uint32_t)0x02000000) /* CH32 Medium-density devices: Write protection of page 100 to 103 */ +#define FLASH_WRProt_Pages104to107 ((uint32_t)0x04000000) /* CH32 Medium-density devices: Write protection of page 104 to 107 */ +#define FLASH_WRProt_Pages108to111 ((uint32_t)0x08000000) /* CH32 Medium-density devices: Write protection of page 108 to 111 */ +#define FLASH_WRProt_Pages112to115 ((uint32_t)0x10000000) /* CH32 Medium-density devices: Write protection of page 112 to 115 */ +#define FLASH_WRProt_Pages116to119 ((uint32_t)0x20000000) /* CH32 Medium-density devices: Write protection of page 115 to 119 */ +#define FLASH_WRProt_Pages120to123 ((uint32_t)0x40000000) /* CH32 Medium-density devices: Write protection of page 120 to 123 */ +#define FLASH_WRProt_Pages124to127 ((uint32_t)0x80000000) /* CH32 Medium-density devices: Write protection of page 124 to 127 */ + +#define FLASH_WRProt_Pages62to255 ((uint32_t)0x80000000) /* CH32 Medium-density devices: Write protection of page 62 to 255 */ + +#define FLASH_WRProt_AllPages ((uint32_t)0xFFFFFFFF) /* Write protection of all Pages */ + +/* Option_Bytes_IWatchdog */ +#define OB_IWDG_SW ((uint16_t)0x0001) /* Software IWDG selected */ +#define OB_IWDG_HW ((uint16_t)0x0000) /* Hardware IWDG selected */ + +/* Option_Bytes_nRST_STOP */ +#define OB_STOP_NoRST ((uint16_t)0x0002) /* No reset generated when entering in STOP */ +#define OB_STOP_RST ((uint16_t)0x0000) /* Reset generated when entering in STOP */ + +/* Option_Bytes_nRST_STDBY */ +#define OB_STDBY_NoRST ((uint16_t)0x0004) /* No reset generated when entering in STANDBY */ +#define OB_STDBY_RST ((uint16_t)0x0000) /* Reset generated when entering in STANDBY */ + +/* FLASH_Interrupts */ +#define FLASH_IT_ERROR ((uint32_t)0x00000400) /* FPEC error interrupt source */ +#define FLASH_IT_EOP ((uint32_t)0x00001000) /* End of FLASH Operation Interrupt source */ +#define FLASH_IT_BANK1_ERROR FLASH_IT_ERROR /* FPEC BANK1 error interrupt source */ +#define FLASH_IT_BANK1_EOP FLASH_IT_EOP /* End of FLASH BANK1 Operation Interrupt source */ + +/* FLASH_Flags */ +#define FLASH_FLAG_BSY ((uint32_t)0x00000001) /* FLASH Busy flag */ +#define FLASH_FLAG_EOP ((uint32_t)0x00000020) /* FLASH End of Operation flag */ +#define FLASH_FLAG_PGERR ((uint32_t)0x00000004) /* FLASH Program error flag */ +#define FLASH_FLAG_WRPRTERR ((uint32_t)0x00000010) /* FLASH Write protected error flag */ +#define FLASH_FLAG_OPTERR ((uint32_t)0x00000001) /* FLASH Option Byte error flag */ + +#define FLASH_FLAG_BANK1_BSY FLASH_FLAG_BSY /* FLASH BANK1 Busy flag*/ +#define FLASH_FLAG_BANK1_EOP FLASH_FLAG_EOP /* FLASH BANK1 End of Operation flag */ +#define FLASH_FLAG_BANK1_PGERR FLASH_FLAG_PGERR /* FLASH BANK1 Program error flag */ +#define FLASH_FLAG_BANK1_WRPRTERR FLASH_FLAG_WRPRTERR /* FLASH BANK1 Write protected error flag */ + + +/*Functions used for all devices*/ +void FLASH_SetLatency(uint32_t FLASH_Latency); +void FLASH_HalfCycleAccessCmd(uint32_t FLASH_HalfCycleAccess); +void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer); +void FLASH_Unlock(void); +void FLASH_Lock(void); +FLASH_Status FLASH_ErasePage(uint32_t Page_Address); +FLASH_Status FLASH_EraseAllPages(void); +FLASH_Status FLASH_EraseOptionBytes(void); +FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data); +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); +FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data); +FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages); +FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState); +FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY); +uint32_t FLASH_GetUserOptionByte(void); +uint32_t FLASH_GetWriteProtectionOptionByte(void); +FlagStatus FLASH_GetReadOutProtectionStatus(void); +FlagStatus FLASH_GetPrefetchBufferStatus(void); +void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState); +FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG); +void FLASH_ClearFlag(uint32_t FLASH_FLAG); +FLASH_Status FLASH_GetStatus(void); +FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout); +void FLASH_Unlock_Fast(void); +void FLASH_Lock_Fast(void); +void FLASH_ErasePage_Fast(uint32_t Page_Address); +void FLASH_EraseBlock_32K_Fast(uint32_t Block_Address); +void FLASH_EraseBlock_64K_Fast(uint32_t Block_Address); +void FLASH_ProgramPage_Fast(uint32_t Page_Address, uint32_t* pbuf); + +/* New function used for all devices */ +void FLASH_UnlockBank1(void); +void FLASH_LockBank1(void); +FLASH_Status FLASH_EraseAllBank1Pages(void); +FLASH_Status FLASH_GetBank1Status(void); +FLASH_Status FLASH_WaitForLastBank1Operation(uint32_t Timeout); + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_fsmc.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_fsmc.h new file mode 100644 index 00000000..2e77ea53 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_fsmc.h @@ -0,0 +1,318 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_fsmc.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the FSMC +* firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_FSMC_H +#define __CH32V30x_FSMC_H + +#ifdef __cplusplus + extern "C" { +#endif + + +#include "ch32v30x.h" + + +/* FSMC Init structure definition */ +typedef struct +{ + uint32_t FSMC_AddressSetupTime; /* Defines the number of HCLK cycles to configure + the duration of the address setup time. + This parameter can be a value between 0 and 0xF. + @note: It is not used with synchronous NOR Flash memories. */ + + uint32_t FSMC_AddressHoldTime; /* Defines the number of HCLK cycles to configure + the duration of the address hold time. + This parameter can be a value between 0 and 0xF. + @note: It is not used with synchronous NOR Flash memories.*/ + + uint32_t FSMC_DataSetupTime; /* Defines the number of HCLK cycles to configure + the duration of the data setup time. + This parameter can be a value between 0 and 0xFF. + @note: It is used for SRAMs, ROMs and asynchronous multiplexed NOR Flash memories. */ + + uint32_t FSMC_BusTurnAroundDuration; /* Defines the number of HCLK cycles to configure + the duration of the bus turnaround. + This parameter can be a value between 0 and 0xF. + @note: It is only used for multiplexed NOR Flash memories. */ + + uint32_t FSMC_CLKDivision; /* Defines the period of CLK clock output signal, expressed in number of HCLK cycles. + This parameter can be a value between 1 and 0xF. + @note: This parameter is not used for asynchronous NOR Flash, SRAM or ROM accesses. */ + + uint32_t FSMC_DataLatency; /* Defines the number of memory clock cycles to issue + to the memory before getting the first data. + The value of this parameter depends on the memory type as shown below: + - It must be set to 0 in case of a CRAM + - It is don't care in asynchronous NOR, SRAM or ROM accesses + - It may assume a value between 0 and 0xF in NOR Flash memories + with synchronous burst mode enable */ + + uint32_t FSMC_AccessMode; /* Specifies the asynchronous access mode. + This parameter can be a value of @ref FSMC_Access_Mode */ +}FSMC_NORSRAMTimingInitTypeDef; + + +typedef struct +{ + uint32_t FSMC_Bank; /* Specifies the NOR/SRAM memory bank that will be used. + This parameter can be a value of @ref FSMC_NORSRAM_Bank */ + + uint32_t FSMC_DataAddressMux; /* Specifies whether the address and data values are + multiplexed on the databus or not. + This parameter can be a value of @ref FSMC_Data_Address_Bus_Multiplexing */ + + uint32_t FSMC_MemoryType; /* Specifies the type of external memory attached to + the corresponding memory bank. + This parameter can be a value of @ref FSMC_Memory_Type */ + + uint32_t FSMC_MemoryDataWidth; /* Specifies the external memory device width. + This parameter can be a value of @ref FSMC_Data_Width */ + + uint32_t FSMC_BurstAccessMode; /* Enables or disables the burst access mode for Flash memory, + valid only with synchronous burst Flash memories. + This parameter can be a value of @ref FSMC_Burst_Access_Mode */ + + uint32_t FSMC_AsynchronousWait; /* Enables or disables wait signal during asynchronous transfers, + valid only with asynchronous Flash memories. + This parameter can be a value of @ref FSMC_AsynchronousWait */ + + uint32_t FSMC_WaitSignalPolarity; /* Specifies the wait signal polarity, valid only when accessing + the Flash memory in burst mode. + This parameter can be a value of @ref FSMC_Wait_Signal_Polarity */ + + uint32_t FSMC_WrapMode; /* Enables or disables the Wrapped burst access mode for Flash + memory, valid only when accessing Flash memories in burst mode. + This parameter can be a value of @ref FSMC_Wrap_Mode */ + + uint32_t FSMC_WaitSignalActive; /* Specifies if the wait signal is asserted by the memory one + clock cycle before the wait state or during the wait state, + valid only when accessing memories in burst mode. + This parameter can be a value of @ref FSMC_Wait_Timing */ + + uint32_t FSMC_WriteOperation; /* Enables or disables the write operation in the selected bank by the FSMC. + This parameter can be a value of @ref FSMC_Write_Operation */ + + uint32_t FSMC_WaitSignal; /* Enables or disables the wait-state insertion via wait + signal, valid for Flash memory access in burst mode. + This parameter can be a value of @ref FSMC_Wait_Signal */ + + uint32_t FSMC_ExtendedMode; /* Enables or disables the extended mode. + This parameter can be a value of @ref FSMC_Extended_Mode */ + + uint32_t FSMC_WriteBurst; /* Enables or disables the write burst operation. + This parameter can be a value of @ref FSMC_Write_Burst */ + + FSMC_NORSRAMTimingInitTypeDef* FSMC_ReadWriteTimingStruct; /* Timing Parameters for write and read access if the ExtendedMode is not used*/ + + FSMC_NORSRAMTimingInitTypeDef* FSMC_WriteTimingStruct; /* Timing Parameters for write access if the ExtendedMode is used*/ +}FSMC_NORSRAMInitTypeDef; + + +typedef struct +{ + uint32_t FSMC_SetupTime; /* Defines the number of HCLK cycles to setup address before + the command assertion for NAND-Flash read or write access + to common/Attribute or I/O memory space (depending on + the memory space timing to be configured). + This parameter can be a value between 0 and 0xFF.*/ + + uint32_t FSMC_WaitSetupTime; /* Defines the minimum number of HCLK cycles to assert the + command for NAND-Flash read or write access to + common/Attribute or I/O memory space (depending on the + memory space timing to be configured). + This parameter can be a number between 0x00 and 0xFF */ + + uint32_t FSMC_HoldSetupTime; /* Defines the number of HCLK clock cycles to hold address + (and data for write access) after the command deassertion + for NAND-Flash read or write access to common/Attribute + or I/O memory space (depending on the memory space timing + to be configured). + This parameter can be a number between 0x00 and 0xFF */ + + uint32_t FSMC_HiZSetupTime; /* Defines the number of HCLK clock cycles during which the + databus is kept in HiZ after the start of a NAND-Flash + write access to common/Attribute or I/O memory space (depending + on the memory space timing to be configured). + This parameter can be a number between 0x00 and 0xFF */ +}FSMC_NAND_PCCARDTimingInitTypeDef; + + +typedef struct +{ + uint32_t FSMC_Bank; /* Specifies the NAND memory bank that will be used. + This parameter can be a value of @ref FSMC_NAND_Bank */ + + uint32_t FSMC_Waitfeature; /* Enables or disables the Wait feature for the NAND Memory Bank. + This parameter can be any value of @ref FSMC_Wait_feature */ + + uint32_t FSMC_MemoryDataWidth; /* Specifies the external memory device width. + This parameter can be any value of @ref FSMC_Data_Width */ + + uint32_t FSMC_ECC; /* Enables or disables the ECC computation. + This parameter can be any value of @ref FSMC_ECC */ + + uint32_t FSMC_ECCPageSize; /* Defines the page size for the extended ECC. + This parameter can be any value of @ref FSMC_ECC_Page_Size */ + + uint32_t FSMC_TCLRSetupTime; /* Defines the number of HCLK cycles to configure the + delay between CLE low and RE low. + This parameter can be a value between 0 and 0xFF. */ + + uint32_t FSMC_TARSetupTime; /* Defines the number of HCLK cycles to configure the + delay between ALE low and RE low. + This parameter can be a number between 0x0 and 0xFF */ + + FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_CommonSpaceTimingStruct; /* FSMC Common Space Timing */ + + FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_AttributeSpaceTimingStruct; /* FSMC Attribute Space Timing */ +}FSMC_NANDInitTypeDef; + + +typedef struct +{ + uint32_t FSMC_Waitfeature; /* Enables or disables the Wait feature for the Memory Bank. + This parameter can be any value of @ref FSMC_Wait_feature */ + + uint32_t FSMC_TCLRSetupTime; /* Defines the number of HCLK cycles to configure the + delay between CLE low and RE low. + This parameter can be a value between 0 and 0xFF. */ + + uint32_t FSMC_TARSetupTime; /* Defines the number of HCLK cycles to configure the + delay between ALE low and RE low. + This parameter can be a number between 0x0 and 0xFF */ + + + FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_CommonSpaceTimingStruct; /* FSMC Common Space Timing */ + + FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_AttributeSpaceTimingStruct; /* FSMC Attribute Space Timing */ + + FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_IOSpaceTimingStruct; /* FSMC IO Space Timing */ +}FSMC_PCCARDInitTypeDef; + + +/* FSMC_NORSRAM_Bank */ +#define FSMC_Bank1_NORSRAM1 ((uint32_t)0x00000000) +#define FSMC_Bank1_NORSRAM2 ((uint32_t)0x00000002) +#define FSMC_Bank1_NORSRAM3 ((uint32_t)0x00000004) +#define FSMC_Bank1_NORSRAM4 ((uint32_t)0x00000006) + +/* FSMC_NAND_Bank */ +#define FSMC_Bank2_NAND ((uint32_t)0x00000010) +#define FSMC_Bank3_NAND ((uint32_t)0x00000100) + +/* FSMC_PCCARD_Bank */ +#define FSMC_Bank4_PCCARD ((uint32_t)0x00001000) + +/* FSMC_Data_Address_Bus_Multiplexing */ +#define FSMC_DataAddressMux_Disable ((uint32_t)0x00000000) +#define FSMC_DataAddressMux_Enable ((uint32_t)0x00000002) + +/* FSMC_Memory_Type */ +#define FSMC_MemoryType_SRAM ((uint32_t)0x00000000) +#define FSMC_MemoryType_PSRAM ((uint32_t)0x00000004) +#define FSMC_MemoryType_NOR ((uint32_t)0x00000008) + +/* FSMC_Data_Width */ +#define FSMC_MemoryDataWidth_8b ((uint32_t)0x00000000) +#define FSMC_MemoryDataWidth_16b ((uint32_t)0x00000010) + +/* FSMC_Burst_Access_Mode */ +#define FSMC_BurstAccessMode_Disable ((uint32_t)0x00000000) +#define FSMC_BurstAccessMode_Enable ((uint32_t)0x00000100) + +/* FSMC_AsynchronousWait */ +#define FSMC_AsynchronousWait_Disable ((uint32_t)0x00000000) +#define FSMC_AsynchronousWait_Enable ((uint32_t)0x00008000) + +/* FSMC_Wait_Signal_Polarity */ +#define FSMC_WaitSignalPolarity_Low ((uint32_t)0x00000000) +#define FSMC_WaitSignalPolarity_High ((uint32_t)0x00000200) + +/* FSMC_Wrap_Mode */ +#define FSMC_WrapMode_Disable ((uint32_t)0x00000000) +#define FSMC_WrapMode_Enable ((uint32_t)0x00000400) + +/* FSMC_Wait_Timing */ +#define FSMC_WaitSignalActive_BeforeWaitState ((uint32_t)0x00000000) +#define FSMC_WaitSignalActive_DuringWaitState ((uint32_t)0x00000800) + +/* FSMC_Write_Operation */ +#define FSMC_WriteOperation_Disable ((uint32_t)0x00000000) +#define FSMC_WriteOperation_Enable ((uint32_t)0x00001000) + +/* FSMC_Wait_Signal */ +#define FSMC_WaitSignal_Disable ((uint32_t)0x00000000) +#define FSMC_WaitSignal_Enable ((uint32_t)0x00002000) + +/* FSMC_Extended_Mode */ +#define FSMC_ExtendedMode_Disable ((uint32_t)0x00000000) +#define FSMC_ExtendedMode_Enable ((uint32_t)0x00004000) + +/* FSMC_Write_Burst */ +#define FSMC_WriteBurst_Disable ((uint32_t)0x00000000) +#define FSMC_WriteBurst_Enable ((uint32_t)0x00080000) + +/* FSMC_Access_Mode */ +#define FSMC_AccessMode_A ((uint32_t)0x00000000) +#define FSMC_AccessMode_B ((uint32_t)0x10000000) +#define FSMC_AccessMode_C ((uint32_t)0x20000000) +#define FSMC_AccessMode_D ((uint32_t)0x30000000) + +/* FSMC_Wait_feature */ +#define FSMC_Waitfeature_Disable ((uint32_t)0x00000000) +#define FSMC_Waitfeature_Enable ((uint32_t)0x00000002) + +/* FSMC_ECC */ +#define FSMC_ECC_Disable ((uint32_t)0x00000000) +#define FSMC_ECC_Enable ((uint32_t)0x00000040) + +/* FSMC_ECC_Page_Size */ +#define FSMC_ECCPageSize_256Bytes ((uint32_t)0x00000000) +#define FSMC_ECCPageSize_512Bytes ((uint32_t)0x00020000) +#define FSMC_ECCPageSize_1024Bytes ((uint32_t)0x00040000) +#define FSMC_ECCPageSize_2048Bytes ((uint32_t)0x00060000) +#define FSMC_ECCPageSize_4096Bytes ((uint32_t)0x00080000) +#define FSMC_ECCPageSize_8192Bytes ((uint32_t)0x000A0000) + +/* FSMC_Interrupt_sources */ +#define FSMC_IT_RisingEdge ((uint32_t)0x00000008) +#define FSMC_IT_Level ((uint32_t)0x00000010) +#define FSMC_IT_FallingEdge ((uint32_t)0x00000020) + +/* FSMC_Flags */ +#define FSMC_FLAG_RisingEdge ((uint32_t)0x00000001) +#define FSMC_FLAG_Level ((uint32_t)0x00000002) +#define FSMC_FLAG_FallingEdge ((uint32_t)0x00000004) +#define FSMC_FLAG_FEMPT ((uint32_t)0x00000040) + + +void FSMC_NORSRAMDeInit(uint32_t FSMC_Bank); +void FSMC_NANDDeInit(uint32_t FSMC_Bank); +void FSMC_PCCARDDeInit(void); +void FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct); +void FSMC_NANDInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct); +void FSMC_PCCARDInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct); +void FSMC_NORSRAMStructInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct); +void FSMC_NANDStructInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct); +void FSMC_PCCARDStructInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct); +void FSMC_NORSRAMCmd(uint32_t FSMC_Bank, FunctionalState NewState); +void FSMC_NANDCmd(uint32_t FSMC_Bank, FunctionalState NewState); +void FSMC_PCCARDCmd(FunctionalState NewState); +void FSMC_NANDECCCmd(uint32_t FSMC_Bank, FunctionalState NewState); +uint32_t FSMC_GetECC(uint32_t FSMC_Bank); +void FSMC_ITConfig(uint32_t FSMC_Bank, uint32_t FSMC_IT, FunctionalState NewState); +FlagStatus FSMC_GetFlagStatus(uint32_t FSMC_Bank, uint32_t FSMC_FLAG); +void FSMC_ClearFlag(uint32_t FSMC_Bank, uint32_t FSMC_FLAG); +ITStatus FSMC_GetITStatus(uint32_t FSMC_Bank, uint32_t FSMC_IT); +void FSMC_ClearITPendingBit(uint32_t FSMC_Bank, uint32_t FSMC_IT); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x_gpio.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_gpio.h similarity index 82% rename from demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x_gpio.h rename to demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_gpio.h index efc9f3cf..99da3e4c 100644 --- a/demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x_gpio.h +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_gpio.h @@ -75,10 +75,9 @@ typedef enum #define GPIO_Pin_All ((uint16_t)0xFFFF) /* All pins selected */ /* GPIO_Remap_define */ -/* PCFR1 */ #define GPIO_Remap_SPI1 ((uint32_t)0x00000001) /* SPI1 Alternate Function mapping */ #define GPIO_Remap_I2C1 ((uint32_t)0x00000002) /* I2C1 Alternate Function mapping */ -#define GPIO_Remap_USART1 ((uint32_t)0x00000004) /* USART1 Alternate Function mapping low bit */ +#define GPIO_Remap_USART1 ((uint32_t)0x00000004) /* USART1 Alternate Function mapping */ #define GPIO_Remap_USART2 ((uint32_t)0x00000008) /* USART2 Alternate Function mapping */ #define GPIO_PartialRemap_USART3 ((uint32_t)0x00140010) /* USART3 Partial Alternate Function mapping */ #define GPIO_FullRemap_USART3 ((uint32_t)0x00140030) /* USART3 Full Alternate Function mapping */ @@ -100,35 +99,21 @@ typedef enum #define GPIO_Remap_ADC2_ETRGREG ((uint32_t)0x00200010) /* ADC2 External Trigger Regular Conversion remapping */ #define GPIO_Remap_ETH ((uint32_t)0x00200020) /* Ethernet remapping (only for Connectivity line devices) */ #define GPIO_Remap_CAN2 ((uint32_t)0x00200040) /* CAN2 remapping (only for Connectivity line devices) */ -#define GPIO_Remap_MII_RMII_SEL ((uint32_t)0x00200080) /* MII or RMII selection */ #define GPIO_Remap_SWJ_NoJTRST ((uint32_t)0x00300100) /* Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST */ #define GPIO_Remap_SWJ_JTAGDisable ((uint32_t)0x00300200) /* JTAG-DP Disabled and SW-DP Enabled */ #define GPIO_Remap_SWJ_Disable ((uint32_t)0x00300400) /* Full SWJ Disabled (JTAG-DP + SW-DP) */ -#define GPIO_Remap_SPI3 ((uint32_t)0x00201000) /* SPI3/I2S3 Alternate Function mapping (only for Connectivity line devices) */ +#define GPIO_Remap_SPI3 ((uint32_t)0x00201100) /* SPI3/I2S3 Alternate Function mapping (only for Connectivity line devices) */ #define GPIO_Remap_TIM2ITR1_PTP_SOF ((uint32_t)0x00202000) /* Ethernet PTP output or USB OTG SOF (Start of Frame) connected to TIM2 Internal Trigger 1 for calibration (only for Connectivity line devices) */ #define GPIO_Remap_PTP_PPS ((uint32_t)0x00204000) /* Ethernet MAC PPS_PTS output on PB05 (only for Connectivity line devices) */ - -/* PCFR2 */ -#define GPIO_Remap_TIM8 ((uint32_t)0x80000004) /* TIM8 Alternate Function mapping */ -#define GPIO_PartialRemap_TIM9 ((uint32_t)0x80130008) /* TIM9 Partial Alternate Function mapping */ -#define GPIO_FullRemap_TIM9 ((uint32_t)0x80130010) /* TIM9 Full Alternate Function mapping */ -#define GPIO_PartialRemap_TIM10 ((uint32_t)0x80150020) /* TIM10 Partial Alternate Function mapping */ -#define GPIO_FullRemap_TIM10 ((uint32_t)0x80150040) /* TIM10 Full Alternate Function mapping */ -#define GPIO_Remap_FSMC_NADV ((uint32_t)0x80000400) /* FSMC_NADV Alternate Function mapping */ -#define GPIO_PartialRemap_USART4 ((uint32_t)0x80300001) /* USART4 Partial Alternate Function mapping */ -#define GPIO_FullRemap_USART4 ((uint32_t)0x80300002) /* USART4 Full Alternate Function mapping */ -#define GPIO_PartialRemap_USART5 ((uint32_t)0x80320004) /* USART5 Partial Alternate Function mapping */ -#define GPIO_FullRemap_USART5 ((uint32_t)0x80320008) /* USART5 Full Alternate Function mapping */ -#define GPIO_PartialRemap_USART6 ((uint32_t)0x80340010) /* USART6 Partial Alternate Function mapping */ -#define GPIO_FullRemap_USART6 ((uint32_t)0x80340020) /* USART6 Full Alternate Function mapping */ -#define GPIO_PartialRemap_USART7 ((uint32_t)0x80360040) /* USART7 Partial Alternate Function mapping */ -#define GPIO_FullRemap_USART7 ((uint32_t)0x80360080) /* USART7 Full Alternate Function mapping */ -#define GPIO_PartialRemap_USART8 ((uint32_t)0x80380100) /* USART8 Partial Alternate Function mapping */ -#define GPIO_FullRemap_USART8 ((uint32_t)0x80380200) /* USART8 Full Alternate Function mapping */ -#define GPIO_Remap_USART1_HighBit ((uint32_t)0x80200400) /* USART1 Alternate Function mapping high bit */ - +#define GPIO_Remap_TIM9 ((uint32_t)0x80000020) /* TIM9 Alternate Function mapping (only for XL-density devices) */ +#define GPIO_Remap_TIM10 ((uint32_t)0x80000040) /* TIM10 Alternate Function mapping (only for XL-density devices) */ +#define GPIO_Remap_FSMC_NADV ((uint32_t)0x80000400) /* FSMC_NADV Alternate Function mapping (only for High density Value line and XL-density devices) */ +#define GPIO_Remap_TIM1_DMA ((uint32_t)0x80000010) /* TIM1 DMA requests mapping (only for Value line devices) */ +#define GPIO_Remap_TIM67_DAC_DMA ((uint32_t)0x80000800) /* TIM6/TIM7 and DAC DMA requests remapping (only for High density Value line devices) */ +#define GPIO_Remap_MISC ((uint32_t)0x80002000) /* Miscellaneous Remap (DMA2 Channel5 Position and DAC Trigger remapping, + only for High density Value line devices) */ /* GPIO_Port_Sources */ #define GPIO_PortSourceGPIOA ((uint8_t)0x00) diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_i2c.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_i2c.h new file mode 100644 index 00000000..60c8d6fc --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_i2c.h @@ -0,0 +1,208 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_i2c.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* I2C firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_I2C_H +#define __CH32V30x_I2C_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* I2C Init structure definition */ +typedef struct +{ + uint32_t I2C_ClockSpeed; /* Specifies the clock frequency. + This parameter must be set to a value lower than 400kHz */ + + uint16_t I2C_Mode; /* Specifies the I2C mode. + This parameter can be a value of @ref I2C_mode */ + + uint16_t I2C_DutyCycle; /* Specifies the I2C fast mode duty cycle. + This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */ + + uint16_t I2C_OwnAddress1; /* Specifies the first device own address. + This parameter can be a 7-bit or 10-bit address. */ + + uint16_t I2C_Ack; /* Enables or disables the acknowledgement. + This parameter can be a value of @ref I2C_acknowledgement */ + + uint16_t I2C_AcknowledgedAddress; /* Specifies if 7-bit or 10-bit address is acknowledged. + This parameter can be a value of @ref I2C_acknowledged_address */ +}I2C_InitTypeDef; + +/* I2C_mode */ +#define I2C_Mode_I2C ((uint16_t)0x0000) +#define I2C_Mode_SMBusDevice ((uint16_t)0x0002) +#define I2C_Mode_SMBusHost ((uint16_t)0x000A) + +/* I2C_duty_cycle_in_fast_mode */ +#define I2C_DutyCycle_16_9 ((uint16_t)0x4000) /* I2C fast mode Tlow/Thigh = 16/9 */ +#define I2C_DutyCycle_2 ((uint16_t)0xBFFF) /* I2C fast mode Tlow/Thigh = 2 */ + +/* I2C_acknowledgement */ +#define I2C_Ack_Enable ((uint16_t)0x0400) +#define I2C_Ack_Disable ((uint16_t)0x0000) + +/* I2C_transfer_direction */ +#define I2C_Direction_Transmitter ((uint8_t)0x00) +#define I2C_Direction_Receiver ((uint8_t)0x01) + +/* I2C_acknowledged_address */ +#define I2C_AcknowledgedAddress_7bit ((uint16_t)0x4000) +#define I2C_AcknowledgedAddress_10bit ((uint16_t)0xC000) + +/* I2C_registers */ +#define I2C_Register_CTLR1 ((uint8_t)0x00) +#define I2C_Register_CTLR2 ((uint8_t)0x04) +#define I2C_Register_OADDR1 ((uint8_t)0x08) +#define I2C_Register_OADDR2 ((uint8_t)0x0C) +#define I2C_Register_DATAR ((uint8_t)0x10) +#define I2C_Register_STAR1 ((uint8_t)0x14) +#define I2C_Register_STAR2 ((uint8_t)0x18) +#define I2C_Register_CKCFGR ((uint8_t)0x1C) +#define I2C_Register_RTR ((uint8_t)0x20) + +/* I2C_SMBus_alert_pin_level */ +#define I2C_SMBusAlert_Low ((uint16_t)0x2000) +#define I2C_SMBusAlert_High ((uint16_t)0xDFFF) + +/* I2C_PEC_position */ +#define I2C_PECPosition_Next ((uint16_t)0x0800) +#define I2C_PECPosition_Current ((uint16_t)0xF7FF) + +/* I2C_NACK_position */ +#define I2C_NACKPosition_Next ((uint16_t)0x0800) +#define I2C_NACKPosition_Current ((uint16_t)0xF7FF) + +/* I2C_interrupts_definition */ +#define I2C_IT_BUF ((uint16_t)0x0400) +#define I2C_IT_EVT ((uint16_t)0x0200) +#define I2C_IT_ERR ((uint16_t)0x0100) + +/* I2C_interrupts_definition */ +#define I2C_IT_SMBALERT ((uint32_t)0x01008000) +#define I2C_IT_TIMEOUT ((uint32_t)0x01004000) +#define I2C_IT_PECERR ((uint32_t)0x01001000) +#define I2C_IT_OVR ((uint32_t)0x01000800) +#define I2C_IT_AF ((uint32_t)0x01000400) +#define I2C_IT_ARLO ((uint32_t)0x01000200) +#define I2C_IT_BERR ((uint32_t)0x01000100) +#define I2C_IT_TXE ((uint32_t)0x06000080) +#define I2C_IT_RXNE ((uint32_t)0x06000040) +#define I2C_IT_STOPF ((uint32_t)0x02000010) +#define I2C_IT_ADD10 ((uint32_t)0x02000008) +#define I2C_IT_BTF ((uint32_t)0x02000004) +#define I2C_IT_ADDR ((uint32_t)0x02000002) +#define I2C_IT_SB ((uint32_t)0x02000001) + +/* SR2 register flags */ +#define I2C_FLAG_DUALF ((uint32_t)0x00800000) +#define I2C_FLAG_SMBHOST ((uint32_t)0x00400000) +#define I2C_FLAG_SMBDEFAULT ((uint32_t)0x00200000) +#define I2C_FLAG_GENCALL ((uint32_t)0x00100000) +#define I2C_FLAG_TRA ((uint32_t)0x00040000) +#define I2C_FLAG_BUSY ((uint32_t)0x00020000) +#define I2C_FLAG_MSL ((uint32_t)0x00010000) + +/* SR1 register flags */ +#define I2C_FLAG_SMBALERT ((uint32_t)0x10008000) +#define I2C_FLAG_TIMEOUT ((uint32_t)0x10004000) +#define I2C_FLAG_PECERR ((uint32_t)0x10001000) +#define I2C_FLAG_OVR ((uint32_t)0x10000800) +#define I2C_FLAG_AF ((uint32_t)0x10000400) +#define I2C_FLAG_ARLO ((uint32_t)0x10000200) +#define I2C_FLAG_BERR ((uint32_t)0x10000100) +#define I2C_FLAG_TXE ((uint32_t)0x10000080) +#define I2C_FLAG_RXNE ((uint32_t)0x10000040) +#define I2C_FLAG_STOPF ((uint32_t)0x10000010) +#define I2C_FLAG_ADD10 ((uint32_t)0x10000008) +#define I2C_FLAG_BTF ((uint32_t)0x10000004) +#define I2C_FLAG_ADDR ((uint32_t)0x10000002) +#define I2C_FLAG_SB ((uint32_t)0x10000001) + + +/****************I2C Master Events (Events grouped in order of communication)********************/ + +#define I2C_EVENT_MASTER_MODE_SELECT ((uint32_t)0x00030001) /* BUSY, MSL and SB flag */ +#define I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ((uint32_t)0x00070082) /* BUSY, MSL, ADDR, TXE and TRA flags */ +#define I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ((uint32_t)0x00030002) /* BUSY, MSL and ADDR flags */ +#define I2C_EVENT_MASTER_MODE_ADDRESS10 ((uint32_t)0x00030008) /* BUSY, MSL and ADD10 flags */ +#define I2C_EVENT_MASTER_BYTE_RECEIVED ((uint32_t)0x00030040) /* BUSY, MSL and RXNE flags */ +#define I2C_EVENT_MASTER_BYTE_TRANSMITTING ((uint32_t)0x00070080) /* TRA, BUSY, MSL, TXE flags */ +#define I2C_EVENT_MASTER_BYTE_TRANSMITTED ((uint32_t)0x00070084) /* TRA, BUSY, MSL, TXE and BTF flags */ + + +/******************I2C Slave Events (Events grouped in order of communication)******************/ + +#define I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED ((uint32_t)0x00020002) /* BUSY and ADDR flags */ +#define I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */ +#define I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED ((uint32_t)0x00820000) /* DUALF and BUSY flags */ +#define I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED ((uint32_t)0x00860080) /* DUALF, TRA, BUSY and TXE flags */ +#define I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED ((uint32_t)0x00120000) /* GENCALL and BUSY flags */ +#define I2C_EVENT_SLAVE_BYTE_RECEIVED ((uint32_t)0x00020040) /* BUSY and RXNE flags */ +#define I2C_EVENT_SLAVE_STOP_DETECTED ((uint32_t)0x00000010) /* STOPF flag */ +#define I2C_EVENT_SLAVE_BYTE_TRANSMITTED ((uint32_t)0x00060084) /* TRA, BUSY, TXE and BTF flags */ +#define I2C_EVENT_SLAVE_BYTE_TRANSMITTING ((uint32_t)0x00060080) /* TRA, BUSY and TXE flags */ +#define I2C_EVENT_SLAVE_ACK_FAILURE ((uint32_t)0x00000400) /* AF flag */ + + +void I2C_DeInit(I2C_TypeDef* I2Cx); +void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct); +void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct); +void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address); +void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState); +void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data); +uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx); +void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction); +uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register); +void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition); +void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert); +void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition); +void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState); +uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx); +void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState); +void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle); + +/**************************************************************************************** +* I2C State Monitoring Functions +****************************************************************************************/ + +ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT); +uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx); +FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG); + +void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG); +ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT); +void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_iwdg.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_iwdg.h new file mode 100644 index 00000000..9ab8c61e --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_iwdg.h @@ -0,0 +1,54 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_iwdg.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* IWDG firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_IWDG_H +#define __CH32V30x_IWDG_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* IWDG_WriteAccess */ +#define IWDG_WriteAccess_Enable ((uint16_t)0x5555) +#define IWDG_WriteAccess_Disable ((uint16_t)0x0000) + +/* IWDG_prescaler */ +#define IWDG_Prescaler_4 ((uint8_t)0x00) +#define IWDG_Prescaler_8 ((uint8_t)0x01) +#define IWDG_Prescaler_16 ((uint8_t)0x02) +#define IWDG_Prescaler_32 ((uint8_t)0x03) +#define IWDG_Prescaler_64 ((uint8_t)0x04) +#define IWDG_Prescaler_128 ((uint8_t)0x05) +#define IWDG_Prescaler_256 ((uint8_t)0x06) + +/* IWDG_Flag */ +#define IWDG_FLAG_PVU ((uint16_t)0x0001) +#define IWDG_FLAG_RVU ((uint16_t)0x0002) + + +void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess); +void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); +void IWDG_SetReload(uint16_t Reload); +void IWDG_ReloadCounter(void); +void IWDG_Enable(void); +FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + + + diff --git a/demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x_misc.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_misc.h similarity index 100% rename from demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x_misc.h rename to demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_misc.h diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_opa.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_opa.h new file mode 100644 index 00000000..5ffcaf0b --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_opa.h @@ -0,0 +1,72 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_opa.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* OPA firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_OPA_H +#define __CH32V30x_OPA_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +#define OPA_PSEL_OFFSET 3 +#define OPA_NSEL_OFFSET 2 +#define OPA_MODE_OFFSET 1 + + +/* OPA member enumeration */ +typedef enum +{ + OPA1=0, + OPA2, + OPA3, + OPA4 +}OPA_Num_TypeDef; + +/* OPA PSEL enumeration */ +typedef enum +{ + CHP0=0, + CHP1 +}OPA_PSEL_TypeDef; + +/* OPA NSEL enumeration */ +typedef enum +{ + CHN0=0, + CHN1 +}OPA_NSEL_TypeDef; + +/* OPA Mode enumeration */ +typedef enum +{ + OUT_IO_ADC=0, + OUT_IO +}OPA_Mode_TypeDef; + +/* OPA Init Structure definition */ +typedef struct +{ + OPA_Num_TypeDef OPA_NUM; /* Specifies the members of OPA */ + OPA_PSEL_TypeDef PSEL; /* Specifies the positive channel of OPA */ + OPA_NSEL_TypeDef NSEL; /* Specifies the negative channel of OPA */ + OPA_Mode_TypeDef Mode; /* Specifies the mode of OPA */ +}OPA_InitTypeDef; + +void OPA_DeInit(void); +void OPA_Init(OPA_InitTypeDef* OPA_InitStruct); +void OPA_StructInit(OPA_InitTypeDef* OPA_InitStruct); +void OPA_Cmd(OPA_Num_TypeDef OPA_NUM, FunctionalState NewState); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_pwr.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_pwr.h new file mode 100644 index 00000000..8b4490db --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_pwr.h @@ -0,0 +1,62 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_pwr.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the PWR +* firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_PWR_H +#define __CH32V30x_PWR_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* PVD_detection_level */ +#define PWR_PVDLevel_2V2 ((uint32_t)0x00000000) +#define PWR_PVDLevel_2V3 ((uint32_t)0x00000020) +#define PWR_PVDLevel_2V4 ((uint32_t)0x00000040) +#define PWR_PVDLevel_2V5 ((uint32_t)0x00000060) +#define PWR_PVDLevel_2V6 ((uint32_t)0x00000080) +#define PWR_PVDLevel_2V7 ((uint32_t)0x000000A0) +#define PWR_PVDLevel_2V8 ((uint32_t)0x000000C0) +#define PWR_PVDLevel_2V9 ((uint32_t)0x000000E0) + +/* Regulator_state_is_STOP_mode */ +#define PWR_Regulator_ON ((uint32_t)0x00000000) +#define PWR_Regulator_LowPower ((uint32_t)0x00000001) + +/* STOP_mode_entry */ +#define PWR_STOPEntry_WFI ((uint8_t)0x01) +#define PWR_STOPEntry_WFE ((uint8_t)0x02) + +/* PWR_Flag */ +#define PWR_FLAG_WU ((uint32_t)0x00000001) +#define PWR_FLAG_SB ((uint32_t)0x00000002) +#define PWR_FLAG_PVDO ((uint32_t)0x00000004) + + +void PWR_DeInit(void); +void PWR_BackupAccessCmd(FunctionalState NewState); +void PWR_PVDCmd(FunctionalState NewState); +void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel); +void PWR_WakeUpPinCmd(FunctionalState NewState); +void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry); +void PWR_EnterSTANDBYMode(void); +FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG); +void PWR_ClearFlag(uint32_t PWR_FLAG); +void PWR_EnterSTOPMode_RAM(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry); +void PWR_EnterSTOPMode_RAM_LV(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry); +void PWR_EnterSTANDBYMode_RAM(void); +void PWR_EnterSTANDBYMode_RAM_LV(void); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x_rcc.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rcc.h similarity index 96% rename from demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x_rcc.h rename to demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rcc.h index 6bd37a2b..3e0950e2 100644 --- a/demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x_rcc.h +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rcc.h @@ -31,7 +31,8 @@ typedef struct /* PLL_entry_clock_source */ #define RCC_PLLSource_HSI_Div2 ((uint32_t)0x00000000) -#define RCC_PLLSource_PREDIV1 ((uint32_t)0x00010000) +#define RCC_PLLSource_HSE_Div1 ((uint32_t)0x00010000) +#define RCC_PLLSource_HSE_Div2 ((uint32_t)0x00030000) /* PLL_multiplication_factor for other CH32V30x */ #define RCC_PLLMul_2 ((uint32_t)0x00000000) @@ -69,6 +70,7 @@ typedef struct #define RCC_PLLMul_15_EXTEN ((uint32_t)0x00380000) #define RCC_PLLMul_16_EXTEN ((uint32_t)0x003C0000) + /* PREDIV1_division_factor */ #define RCC_PREDIV1_Div1 ((uint32_t)0x00000000) #define RCC_PREDIV1_Div2 ((uint32_t)0x00000001) @@ -211,6 +213,7 @@ typedef struct #define RCC_AHBPeriph_DMA1 ((uint32_t)0x00000001) #define RCC_AHBPeriph_DMA2 ((uint32_t)0x00000002) #define RCC_AHBPeriph_SRAM ((uint32_t)0x00000004) +#define RCC_AHBPeriph_FLITF ((uint32_t)0x00000010) #define RCC_AHBPeriph_CRC ((uint32_t)0x00000040) #define RCC_AHBPeriph_FSMC ((uint32_t)0x00000100) #define RCC_AHBPeriph_RNG ((uint32_t)0x00000200) @@ -229,14 +232,21 @@ typedef struct #define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010) #define RCC_APB2Periph_GPIOD ((uint32_t)0x00000020) #define RCC_APB2Periph_GPIOE ((uint32_t)0x00000040) +#define RCC_APB2Periph_GPIOF ((uint32_t)0x00000080) +#define RCC_APB2Periph_GPIOG ((uint32_t)0x00000100) #define RCC_APB2Periph_ADC1 ((uint32_t)0x00000200) #define RCC_APB2Periph_ADC2 ((uint32_t)0x00000400) #define RCC_APB2Periph_TIM1 ((uint32_t)0x00000800) #define RCC_APB2Periph_SPI1 ((uint32_t)0x00001000) #define RCC_APB2Periph_TIM8 ((uint32_t)0x00002000) #define RCC_APB2Periph_USART1 ((uint32_t)0x00004000) +#define RCC_APB2Periph_ADC3 ((uint32_t)0x00008000) +#define RCC_APB2Periph_TIM15 ((uint32_t)0x00010000) +#define RCC_APB2Periph_TIM16 ((uint32_t)0x00020000) +#define RCC_APB2Periph_TIM17 ((uint32_t)0x00040000) #define RCC_APB2Periph_TIM9 ((uint32_t)0x00080000) #define RCC_APB2Periph_TIM10 ((uint32_t)0x00100000) +#define RCC_APB2Periph_TIM11 ((uint32_t)0x00200000) /* APB1_peripheral */ #define RCC_APB1Periph_TIM2 ((uint32_t)0x00000001) @@ -263,6 +273,7 @@ typedef struct #define RCC_APB1Periph_BKP ((uint32_t)0x08000000) #define RCC_APB1Periph_PWR ((uint32_t)0x10000000) #define RCC_APB1Periph_DAC ((uint32_t)0x20000000) +#define RCC_APB1Periph_CEC ((uint32_t)0x40000000) /* Clock_source_to_output_on_MCO_pin */ #define RCC_MCO_NoClock ((uint8_t)0x00) diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rng.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rng.h new file mode 100644 index 00000000..a7d7e793 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rng.h @@ -0,0 +1,39 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_rng.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* RNG firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_RNG_H +#define __CH32V30x_RNG_H + +#ifdef __cplusplus + extern "C" { +#endif +#include "ch32v30x.h" + + /* RNG_flags_definition*/ +#define RNG_FLAG_DRDY ((uint8_t)0x0001) /* Data ready */ +#define RNG_FLAG_CECS ((uint8_t)0x0002) /* Clock error current status */ +#define RNG_FLAG_SECS ((uint8_t)0x0004) /* Seed error current status */ + +/* RNG_interrupts_definition */ +#define RNG_IT_CEI ((uint8_t)0x20) /* Clock error interrupt */ +#define RNG_IT_SEI ((uint8_t)0x40) /* Seed error interrupt */ + + +void RNG_Cmd(FunctionalState NewState); +uint32_t RNG_GetRandomNumber(void); +void RNG_ITConfig(FunctionalState NewState); +FlagStatus RNG_GetFlagStatus(uint8_t RNG_FLAG); +void RNG_ClearFlag(uint8_t RNG_FLAG); +ITStatus RNG_GetITStatus(uint8_t RNG_IT); +void RNG_ClearITPendingBit(uint8_t RNG_IT); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rtc.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rtc.h new file mode 100644 index 00000000..a6209541 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_rtc.h @@ -0,0 +1,52 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_rtc.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the RTC +* firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_RTC_H +#define __CH32V30x_RTC_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + + +/* RTC_interrupts_define */ +#define RTC_IT_OW ((uint16_t)0x0004) /* Overflow interrupt */ +#define RTC_IT_ALR ((uint16_t)0x0002) /* Alarm interrupt */ +#define RTC_IT_SEC ((uint16_t)0x0001) /* Second interrupt */ + +/* RTC_interrupts_flags */ +#define RTC_FLAG_RTOFF ((uint16_t)0x0020) /* RTC Operation OFF flag */ +#define RTC_FLAG_RSF ((uint16_t)0x0008) /* Registers Synchronized flag */ +#define RTC_FLAG_OW ((uint16_t)0x0004) /* Overflow flag */ +#define RTC_FLAG_ALR ((uint16_t)0x0002) /* Alarm flag */ +#define RTC_FLAG_SEC ((uint16_t)0x0001) /* Second flag */ + + +void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState); +void RTC_EnterConfigMode(void); +void RTC_ExitConfigMode(void); +uint32_t RTC_GetCounter(void); +void RTC_SetCounter(uint32_t CounterValue); +void RTC_SetPrescaler(uint32_t PrescalerValue); +void RTC_SetAlarm(uint32_t AlarmValue); +uint32_t RTC_GetDivider(void); +void RTC_WaitForLastTask(void); +void RTC_WaitForSynchro(void); +FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG); +void RTC_ClearFlag(uint16_t RTC_FLAG); +ITStatus RTC_GetITStatus(uint16_t RTC_IT); +void RTC_ClearITPendingBit(uint16_t RTC_IT); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_sdio.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_sdio.h new file mode 100644 index 00000000..79eb443f --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_sdio.h @@ -0,0 +1,252 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_sdio.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the SDIO +* firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_SDIO_H +#define __CH32V30x_SDIO_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* SDIO Init structure definition */ +typedef struct +{ + uint32_t SDIO_ClockEdge; /* Specifies the clock transition on which the bit capture is made. + This parameter can be a value of @ref SDIO_Clock_Edge */ + + uint32_t SDIO_ClockBypass; /* Specifies whether the SDIO Clock divider bypass is + enabled or disabled. + This parameter can be a value of @ref SDIO_Clock_Bypass */ + + uint32_t SDIO_ClockPowerSave; /* Specifies whether SDIO Clock output is enabled or + disabled when the bus is idle. + This parameter can be a value of @ref SDIO_Clock_Power_Save */ + + uint32_t SDIO_BusWide; /* Specifies the SDIO bus width. + This parameter can be a value of @ref SDIO_Bus_Wide */ + + uint32_t SDIO_HardwareFlowControl; /* Specifies whether the SDIO hardware flow control is enabled or disabled. + This parameter can be a value of @ref SDIO_Hardware_Flow_Control */ + + uint8_t SDIO_ClockDiv; /* Specifies the clock frequency of the SDIO controller. + This parameter can be a value between 0x00 and 0xFF. */ + +} SDIO_InitTypeDef; + + +typedef struct +{ + uint32_t SDIO_Argument; /* Specifies the SDIO command argument which is sent + to a card as part of a command message. If a command + contains an argument, it must be loaded into this register + before writing the command to the command register */ + + uint32_t SDIO_CmdIndex; /* Specifies the SDIO command index. It must be lower than 0x40. */ + + uint32_t SDIO_Response; /* Specifies the SDIO response type. + This parameter can be a value of @ref SDIO_Response_Type */ + + uint32_t SDIO_Wait; /* Specifies whether SDIO wait-for-interrupt request is enabled or disabled. + This parameter can be a value of @ref SDIO_Wait_Interrupt_State */ + + uint32_t SDIO_CPSM; /* Specifies whether SDIO Command path state machine (CPSM) + is enabled or disabled. + This parameter can be a value of @ref SDIO_CPSM_State */ +} SDIO_CmdInitTypeDef; + +typedef struct +{ + uint32_t SDIO_DataTimeOut; /* Specifies the data timeout period in card bus clock periods. */ + + uint32_t SDIO_DataLength; /* Specifies the number of data bytes to be transferred. */ + + uint32_t SDIO_DataBlockSize; /* Specifies the data block size for block transfer. + This parameter can be a value of @ref SDIO_Data_Block_Size */ + + uint32_t SDIO_TransferDir; /* Specifies the data transfer direction, whether the transfer + is a read or write. + This parameter can be a value of @ref SDIO_Transfer_Direction */ + + uint32_t SDIO_TransferMode; /* Specifies whether data transfer is in stream or block mode. + This parameter can be a value of @ref SDIO_Transfer_Type */ + + uint32_t SDIO_DPSM; /* Specifies whether SDIO Data path state machine (DPSM) + is enabled or disabled. + This parameter can be a value of @ref SDIO_DPSM_State */ +} SDIO_DataInitTypeDef; + + +/* SDIO_Clock_Edge */ +#define SDIO_ClockEdge_Rising ((uint32_t)0x00000000) +#define SDIO_ClockEdge_Falling ((uint32_t)0x00002000) + +/* SDIO_Clock_Bypass */ +#define SDIO_ClockBypass_Disable ((uint32_t)0x00000000) +#define SDIO_ClockBypass_Enable ((uint32_t)0x00000400) + +/* SDIO_Clock_Power_Save */ +#define SDIO_ClockPowerSave_Disable ((uint32_t)0x00000000) +#define SDIO_ClockPowerSave_Enable ((uint32_t)0x00000200) + +/* SDIO_Bus_Wide */ +#define SDIO_BusWide_1b ((uint32_t)0x00000000) +#define SDIO_BusWide_4b ((uint32_t)0x00000800) +#define SDIO_BusWide_8b ((uint32_t)0x00001000) + +/* SDIO_Hardware_Flow_Control */ +#define SDIO_HardwareFlowControl_Disable ((uint32_t)0x00000000) +#define SDIO_HardwareFlowControl_Enable ((uint32_t)0x00004000) + +/* SDIO_Power_State */ +#define SDIO_PowerState_OFF ((uint32_t)0x00000000) +#define SDIO_PowerState_ON ((uint32_t)0x00000003) + +/* SDIO_Interrupt_sources */ +#define SDIO_IT_CCRCFAIL ((uint32_t)0x00000001) +#define SDIO_IT_DCRCFAIL ((uint32_t)0x00000002) +#define SDIO_IT_CTIMEOUT ((uint32_t)0x00000004) +#define SDIO_IT_DTIMEOUT ((uint32_t)0x00000008) +#define SDIO_IT_TXUNDERR ((uint32_t)0x00000010) +#define SDIO_IT_RXOVERR ((uint32_t)0x00000020) +#define SDIO_IT_CMDREND ((uint32_t)0x00000040) +#define SDIO_IT_CMDSENT ((uint32_t)0x00000080) +#define SDIO_IT_DATAEND ((uint32_t)0x00000100) +#define SDIO_IT_STBITERR ((uint32_t)0x00000200) +#define SDIO_IT_DBCKEND ((uint32_t)0x00000400) +#define SDIO_IT_CMDACT ((uint32_t)0x00000800) +#define SDIO_IT_TXACT ((uint32_t)0x00001000) +#define SDIO_IT_RXACT ((uint32_t)0x00002000) +#define SDIO_IT_TXFIFOHE ((uint32_t)0x00004000) +#define SDIO_IT_RXFIFOHF ((uint32_t)0x00008000) +#define SDIO_IT_TXFIFOF ((uint32_t)0x00010000) +#define SDIO_IT_RXFIFOF ((uint32_t)0x00020000) +#define SDIO_IT_TXFIFOE ((uint32_t)0x00040000) +#define SDIO_IT_RXFIFOE ((uint32_t)0x00080000) +#define SDIO_IT_TXDAVL ((uint32_t)0x00100000) +#define SDIO_IT_RXDAVL ((uint32_t)0x00200000) +#define SDIO_IT_SDIOIT ((uint32_t)0x00400000) +#define SDIO_IT_CEATAEND ((uint32_t)0x00800000) + +/* SDIO_Response_Type */ +#define SDIO_Response_No ((uint32_t)0x00000000) +#define SDIO_Response_Short ((uint32_t)0x00000040) +#define SDIO_Response_Long ((uint32_t)0x000000C0) + +/* SDIO_Wait_Interrupt_State */ +#define SDIO_Wait_No ((uint32_t)0x00000000) +#define SDIO_Wait_IT ((uint32_t)0x00000100) +#define SDIO_Wait_Pend ((uint32_t)0x00000200) + +/* SDIO_CPSM_State */ +#define SDIO_CPSM_Disable ((uint32_t)0x00000000) +#define SDIO_CPSM_Enable ((uint32_t)0x00000400) + +/* SDIO_Response_Registers */ +#define SDIO_RESP1 ((uint32_t)0x00000000) +#define SDIO_RESP2 ((uint32_t)0x00000004) +#define SDIO_RESP3 ((uint32_t)0x00000008) +#define SDIO_RESP4 ((uint32_t)0x0000000C) + +/* SDIO_Data_Block_Size */ +#define SDIO_DataBlockSize_1b ((uint32_t)0x00000000) +#define SDIO_DataBlockSize_2b ((uint32_t)0x00000010) +#define SDIO_DataBlockSize_4b ((uint32_t)0x00000020) +#define SDIO_DataBlockSize_8b ((uint32_t)0x00000030) +#define SDIO_DataBlockSize_16b ((uint32_t)0x00000040) +#define SDIO_DataBlockSize_32b ((uint32_t)0x00000050) +#define SDIO_DataBlockSize_64b ((uint32_t)0x00000060) +#define SDIO_DataBlockSize_128b ((uint32_t)0x00000070) +#define SDIO_DataBlockSize_256b ((uint32_t)0x00000080) +#define SDIO_DataBlockSize_512b ((uint32_t)0x00000090) +#define SDIO_DataBlockSize_1024b ((uint32_t)0x000000A0) +#define SDIO_DataBlockSize_2048b ((uint32_t)0x000000B0) +#define SDIO_DataBlockSize_4096b ((uint32_t)0x000000C0) +#define SDIO_DataBlockSize_8192b ((uint32_t)0x000000D0) +#define SDIO_DataBlockSize_16384b ((uint32_t)0x000000E0) + +/* SDIO_Transfer_Direction */ +#define SDIO_TransferDir_ToCard ((uint32_t)0x00000000) +#define SDIO_TransferDir_ToSDIO ((uint32_t)0x00000002) + +/* SDIO_Transfer_Type */ +#define SDIO_TransferMode_Block ((uint32_t)0x00000000) +#define SDIO_TransferMode_Stream ((uint32_t)0x00000004) + +/* SDIO_DPSM_State */ +#define SDIO_DPSM_Disable ((uint32_t)0x00000000) +#define SDIO_DPSM_Enable ((uint32_t)0x00000001) + +/* SDIO_Flags */ +#define SDIO_FLAG_CCRCFAIL ((uint32_t)0x00000001) +#define SDIO_FLAG_DCRCFAIL ((uint32_t)0x00000002) +#define SDIO_FLAG_CTIMEOUT ((uint32_t)0x00000004) +#define SDIO_FLAG_DTIMEOUT ((uint32_t)0x00000008) +#define SDIO_FLAG_TXUNDERR ((uint32_t)0x00000010) +#define SDIO_FLAG_RXOVERR ((uint32_t)0x00000020) +#define SDIO_FLAG_CMDREND ((uint32_t)0x00000040) +#define SDIO_FLAG_CMDSENT ((uint32_t)0x00000080) +#define SDIO_FLAG_DATAEND ((uint32_t)0x00000100) +#define SDIO_FLAG_STBITERR ((uint32_t)0x00000200) +#define SDIO_FLAG_DBCKEND ((uint32_t)0x00000400) +#define SDIO_FLAG_CMDACT ((uint32_t)0x00000800) +#define SDIO_FLAG_TXACT ((uint32_t)0x00001000) +#define SDIO_FLAG_RXACT ((uint32_t)0x00002000) +#define SDIO_FLAG_TXFIFOHE ((uint32_t)0x00004000) +#define SDIO_FLAG_RXFIFOHF ((uint32_t)0x00008000) +#define SDIO_FLAG_TXFIFOF ((uint32_t)0x00010000) +#define SDIO_FLAG_RXFIFOF ((uint32_t)0x00020000) +#define SDIO_FLAG_TXFIFOE ((uint32_t)0x00040000) +#define SDIO_FLAG_RXFIFOE ((uint32_t)0x00080000) +#define SDIO_FLAG_TXDAVL ((uint32_t)0x00100000) +#define SDIO_FLAG_RXDAVL ((uint32_t)0x00200000) +#define SDIO_FLAG_SDIOIT ((uint32_t)0x00400000) +#define SDIO_FLAG_CEATAEND ((uint32_t)0x00800000) + +/* SDIO_Read_Wait_Mode */ +#define SDIO_ReadWaitMode_CLK ((uint32_t)0x00000001) +#define SDIO_ReadWaitMode_DATA2 ((uint32_t)0x00000000) + + +void SDIO_DeInit(void); +void SDIO_Init(SDIO_InitTypeDef* SDIO_InitStruct); +void SDIO_StructInit(SDIO_InitTypeDef* SDIO_InitStruct); +void SDIO_ClockCmd(FunctionalState NewState); +void SDIO_SetPowerState(uint32_t SDIO_PowerState); +uint32_t SDIO_GetPowerState(void); +void SDIO_ITConfig(uint32_t SDIO_IT, FunctionalState NewState); +void SDIO_DMACmd(FunctionalState NewState); +void SDIO_SendCommand(SDIO_CmdInitTypeDef *SDIO_CmdInitStruct); +void SDIO_CmdStructInit(SDIO_CmdInitTypeDef* SDIO_CmdInitStruct); +uint8_t SDIO_GetCommandResponse(void); +uint32_t SDIO_GetResponse(uint32_t SDIO_RESP); +void SDIO_DataConfig(SDIO_DataInitTypeDef* SDIO_DataInitStruct); +void SDIO_DataStructInit(SDIO_DataInitTypeDef* SDIO_DataInitStruct); +uint32_t SDIO_GetDataCounter(void); +uint32_t SDIO_ReadData(void); +void SDIO_WriteData(uint32_t Data); +uint32_t SDIO_GetFIFOCount(void); +void SDIO_StartSDIOReadWait(FunctionalState NewState); +void SDIO_StopSDIOReadWait(FunctionalState NewState); +void SDIO_SetSDIOReadWaitMode(uint32_t SDIO_ReadWaitMode); +void SDIO_SetSDIOOperation(FunctionalState NewState); +void SDIO_SendSDIOSuspendCmd(FunctionalState NewState); +void SDIO_CommandCompletionCmd(FunctionalState NewState); +void SDIO_CEATAITCmd(FunctionalState NewState); +void SDIO_SendCEATACmd(FunctionalState NewState); +FlagStatus SDIO_GetFlagStatus(uint32_t SDIO_FLAG); +void SDIO_ClearFlag(uint32_t SDIO_FLAG); +ITStatus SDIO_GetITStatus(uint32_t SDIO_IT); +void SDIO_ClearITPendingBit(uint32_t SDIO_IT); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_spi.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_spi.h new file mode 100644 index 00000000..c63e49a2 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_spi.h @@ -0,0 +1,227 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_spi.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* SPI firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_SPI_H +#define __CH32V30x_SPI_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* SPI Init structure definition */ +typedef struct +{ + uint16_t SPI_Direction; /* Specifies the SPI unidirectional or bidirectional data mode. + This parameter can be a value of @ref SPI_data_direction */ + + uint16_t SPI_Mode; /* Specifies the SPI operating mode. + This parameter can be a value of @ref SPI_mode */ + + uint16_t SPI_DataSize; /* Specifies the SPI data size. + This parameter can be a value of @ref SPI_data_size */ + + uint16_t SPI_CPOL; /* Specifies the serial clock steady state. + This parameter can be a value of @ref SPI_Clock_Polarity */ + + uint16_t SPI_CPHA; /* Specifies the clock active edge for the bit capture. + This parameter can be a value of @ref SPI_Clock_Phase */ + + uint16_t SPI_NSS; /* Specifies whether the NSS signal is managed by + hardware (NSS pin) or by software using the SSI bit. + This parameter can be a value of @ref SPI_Slave_Select_management */ + + uint16_t SPI_BaudRatePrescaler; /* Specifies the Baud Rate prescaler value which will be + used to configure the transmit and receive SCK clock. + This parameter can be a value of @ref SPI_BaudRate_Prescaler. + @note The communication clock is derived from the master + clock. The slave clock does not need to be set. */ + + uint16_t SPI_FirstBit; /* Specifies whether data transfers start from MSB or LSB bit. + This parameter can be a value of @ref SPI_MSB_LSB_transmission */ + + uint16_t SPI_CRCPolynomial; /* Specifies the polynomial used for the CRC calculation. */ +}SPI_InitTypeDef; + +/* I2S Init structure definition */ +typedef struct +{ + + uint16_t I2S_Mode; /* Specifies the I2S operating mode. + This parameter can be a value of @ref I2S_Mode */ + + uint16_t I2S_Standard; /* Specifies the standard used for the I2S communication. + This parameter can be a value of @ref I2S_Standard */ + + uint16_t I2S_DataFormat; /* Specifies the data format for the I2S communication. + This parameter can be a value of @ref I2S_Data_Format */ + + uint16_t I2S_MCLKOutput; /* Specifies whether the I2S MCLK output is enabled or not. + This parameter can be a value of @ref I2S_MCLK_Output */ + + uint32_t I2S_AudioFreq; /* Specifies the frequency selected for the I2S communication. + This parameter can be a value of @ref I2S_Audio_Frequency */ + + uint16_t I2S_CPOL; /* Specifies the idle state of the I2S clock. + This parameter can be a value of @ref I2S_Clock_Polarity */ +}I2S_InitTypeDef; + +/* SPI_data_direction */ +#define SPI_Direction_2Lines_FullDuplex ((uint16_t)0x0000) +#define SPI_Direction_2Lines_RxOnly ((uint16_t)0x0400) +#define SPI_Direction_1Line_Rx ((uint16_t)0x8000) +#define SPI_Direction_1Line_Tx ((uint16_t)0xC000) + +/* SPI_mode */ +#define SPI_Mode_Master ((uint16_t)0x0104) +#define SPI_Mode_Slave ((uint16_t)0x0000) + +/* SPI_data_size */ +#define SPI_DataSize_16b ((uint16_t)0x0800) +#define SPI_DataSize_8b ((uint16_t)0x0000) + +/* SPI_Clock_Polarity */ +#define SPI_CPOL_Low ((uint16_t)0x0000) +#define SPI_CPOL_High ((uint16_t)0x0002) + +/* SPI_Clock_Phase */ +#define SPI_CPHA_1Edge ((uint16_t)0x0000) +#define SPI_CPHA_2Edge ((uint16_t)0x0001) + +/* SPI_Slave_Select_management */ +#define SPI_NSS_Soft ((uint16_t)0x0200) +#define SPI_NSS_Hard ((uint16_t)0x0000) + +/* SPI_BaudRate_Prescaler */ +#define SPI_BaudRatePrescaler_2 ((uint16_t)0x0000) +#define SPI_BaudRatePrescaler_4 ((uint16_t)0x0008) +#define SPI_BaudRatePrescaler_8 ((uint16_t)0x0010) +#define SPI_BaudRatePrescaler_16 ((uint16_t)0x0018) +#define SPI_BaudRatePrescaler_32 ((uint16_t)0x0020) +#define SPI_BaudRatePrescaler_64 ((uint16_t)0x0028) +#define SPI_BaudRatePrescaler_128 ((uint16_t)0x0030) +#define SPI_BaudRatePrescaler_256 ((uint16_t)0x0038) + +/* SPI_MSB_LSB_transmission */ +#define SPI_FirstBit_MSB ((uint16_t)0x0000) +#define SPI_FirstBit_LSB ((uint16_t)0x0080) + +/* I2S_Mode */ +#define I2S_Mode_SlaveTx ((uint16_t)0x0000) +#define I2S_Mode_SlaveRx ((uint16_t)0x0100) +#define I2S_Mode_MasterTx ((uint16_t)0x0200) +#define I2S_Mode_MasterRx ((uint16_t)0x0300) + +/* I2S_Standard */ +#define I2S_Standard_Phillips ((uint16_t)0x0000) +#define I2S_Standard_MSB ((uint16_t)0x0010) +#define I2S_Standard_LSB ((uint16_t)0x0020) +#define I2S_Standard_PCMShort ((uint16_t)0x0030) +#define I2S_Standard_PCMLong ((uint16_t)0x00B0) + +/* I2S_Data_Format */ +#define I2S_DataFormat_16b ((uint16_t)0x0000) +#define I2S_DataFormat_16bextended ((uint16_t)0x0001) +#define I2S_DataFormat_24b ((uint16_t)0x0003) +#define I2S_DataFormat_32b ((uint16_t)0x0005) + +/* I2S_MCLK_Output */ +#define I2S_MCLKOutput_Enable ((uint16_t)0x0200) +#define I2S_MCLKOutput_Disable ((uint16_t)0x0000) + +/* I2S_Audio_Frequency */ +#define I2S_AudioFreq_192k ((uint32_t)192000) +#define I2S_AudioFreq_96k ((uint32_t)96000) +#define I2S_AudioFreq_48k ((uint32_t)48000) +#define I2S_AudioFreq_44k ((uint32_t)44100) +#define I2S_AudioFreq_32k ((uint32_t)32000) +#define I2S_AudioFreq_22k ((uint32_t)22050) +#define I2S_AudioFreq_16k ((uint32_t)16000) +#define I2S_AudioFreq_11k ((uint32_t)11025) +#define I2S_AudioFreq_8k ((uint32_t)8000) +#define I2S_AudioFreq_Default ((uint32_t)2) + +/* I2S_Clock_Polarity */ +#define I2S_CPOL_Low ((uint16_t)0x0000) +#define I2S_CPOL_High ((uint16_t)0x0008) + +/* SPI_I2S_DMA_transfer_requests */ +#define SPI_I2S_DMAReq_Tx ((uint16_t)0x0002) +#define SPI_I2S_DMAReq_Rx ((uint16_t)0x0001) + +/* SPI_NSS_internal_software_management */ +#define SPI_NSSInternalSoft_Set ((uint16_t)0x0100) +#define SPI_NSSInternalSoft_Reset ((uint16_t)0xFEFF) + +/* SPI_CRC_Transmit_Receive */ +#define SPI_CRC_Tx ((uint8_t)0x00) +#define SPI_CRC_Rx ((uint8_t)0x01) + +/* SPI_direction_transmit_receive */ +#define SPI_Direction_Rx ((uint16_t)0xBFFF) +#define SPI_Direction_Tx ((uint16_t)0x4000) + +/* SPI_I2S_interrupts_definition */ +#define SPI_I2S_IT_TXE ((uint8_t)0x71) +#define SPI_I2S_IT_RXNE ((uint8_t)0x60) +#define SPI_I2S_IT_ERR ((uint8_t)0x50) +#define SPI_I2S_IT_OVR ((uint8_t)0x56) +#define SPI_IT_MODF ((uint8_t)0x55) +#define SPI_IT_CRCERR ((uint8_t)0x54) +#define I2S_IT_UDR ((uint8_t)0x53) + +/* SPI_I2S_flags_definition */ +#define SPI_I2S_FLAG_RXNE ((uint16_t)0x0001) +#define SPI_I2S_FLAG_TXE ((uint16_t)0x0002) +#define I2S_FLAG_CHSIDE ((uint16_t)0x0004) +#define I2S_FLAG_UDR ((uint16_t)0x0008) +#define SPI_FLAG_CRCERR ((uint16_t)0x0010) +#define SPI_FLAG_MODF ((uint16_t)0x0020) +#define SPI_I2S_FLAG_OVR ((uint16_t)0x0040) +#define SPI_I2S_FLAG_BSY ((uint16_t)0x0080) + + +void SPI_I2S_DeInit(SPI_TypeDef* SPIx); +void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct); +void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct); +void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct); +void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct); +void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState); +void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState); +void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState); +void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState); +void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data); +uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx); +void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft); +void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState); +void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize); +void SPI_TransmitCRC(SPI_TypeDef* SPIx); +void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState); +uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC); +uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx); +void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction); +FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG); +void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG); +ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT); +void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_tim.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_tim.h new file mode 100644 index 00000000..568e65b6 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_tim.h @@ -0,0 +1,513 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_tim.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the +* TIM firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_TIM_H +#define __CH32V30x_TIM_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + +/* TIM Time Base Init structure definition */ +typedef struct +{ + uint16_t TIM_Prescaler; /* Specifies the prescaler value used to divide the TIM clock. + This parameter can be a number between 0x0000 and 0xFFFF */ + + uint16_t TIM_CounterMode; /* Specifies the counter mode. + This parameter can be a value of @ref TIM_Counter_Mode */ + + uint16_t TIM_Period; /* Specifies the period value to be loaded into the active + Auto-Reload Register at the next update event. + This parameter must be a number between 0x0000 and 0xFFFF. */ + + uint16_t TIM_ClockDivision; /* Specifies the clock division. + This parameter can be a value of @ref TIM_Clock_Division_CKD */ + + uint8_t TIM_RepetitionCounter; /* Specifies the repetition counter value. Each time the RCR downcounter + reaches zero, an update event is generated and counting restarts + from the RCR value (N). + This means in PWM mode that (N+1) corresponds to: + - the number of PWM periods in edge-aligned mode + - the number of half PWM period in center-aligned mode + This parameter must be a number between 0x00 and 0xFF. + @note This parameter is valid only for TIM1 and TIM8. */ +} TIM_TimeBaseInitTypeDef; + +/* TIM Output Compare Init structure definition */ +typedef struct +{ + uint16_t TIM_OCMode; /* Specifies the TIM mode. + This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */ + + uint16_t TIM_OutputState; /* Specifies the TIM Output Compare state. + This parameter can be a value of @ref TIM_Output_Compare_state */ + + uint16_t TIM_OutputNState; /* Specifies the TIM complementary Output Compare state. + This parameter can be a value of @ref TIM_Output_Compare_N_state + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t TIM_Pulse; /* Specifies the pulse value to be loaded into the Capture Compare Register. + This parameter can be a number between 0x0000 and 0xFFFF */ + + uint16_t TIM_OCPolarity; /* Specifies the output polarity. + This parameter can be a value of @ref TIM_Output_Compare_Polarity */ + + uint16_t TIM_OCNPolarity; /* Specifies the complementary output polarity. + This parameter can be a value of @ref TIM_Output_Compare_N_Polarity + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t TIM_OCIdleState; /* Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ + + uint16_t TIM_OCNIdleState; /* Specifies the TIM Output Compare pin state during Idle state. + This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State + @note This parameter is valid only for TIM1 and TIM8. */ +} TIM_OCInitTypeDef; + +/* TIM Input Capture Init structure definition */ +typedef struct +{ + uint16_t TIM_Channel; /* Specifies the TIM channel. + This parameter can be a value of @ref TIM_Channel */ + + uint16_t TIM_ICPolarity; /* Specifies the active edge of the input signal. + This parameter can be a value of @ref TIM_Input_Capture_Polarity */ + + uint16_t TIM_ICSelection; /* Specifies the input. + This parameter can be a value of @ref TIM_Input_Capture_Selection */ + + uint16_t TIM_ICPrescaler; /* Specifies the Input Capture Prescaler. + This parameter can be a value of @ref TIM_Input_Capture_Prescaler */ + + uint16_t TIM_ICFilter; /* Specifies the input capture filter. + This parameter can be a number between 0x0 and 0xF */ +} TIM_ICInitTypeDef; + +/* BDTR structure definition */ +typedef struct +{ + uint16_t TIM_OSSRState; /* Specifies the Off-State selection used in Run mode. + This parameter can be a value of @ref OSSR_Off_State_Selection_for_Run_mode_state */ + + uint16_t TIM_OSSIState; /* Specifies the Off-State used in Idle state. + This parameter can be a value of @ref OSSI_Off_State_Selection_for_Idle_mode_state */ + + uint16_t TIM_LOCKLevel; /* Specifies the LOCK level parameters. + This parameter can be a value of @ref Lock_level */ + + uint16_t TIM_DeadTime; /* Specifies the delay time between the switching-off and the + switching-on of the outputs. + This parameter can be a number between 0x00 and 0xFF */ + + uint16_t TIM_Break; /* Specifies whether the TIM Break input is enabled or not. + This parameter can be a value of @ref Break_Input_enable_disable */ + + uint16_t TIM_BreakPolarity; /* Specifies the TIM Break Input pin polarity. + This parameter can be a value of @ref Break_Polarity */ + + uint16_t TIM_AutomaticOutput; /* Specifies whether the TIM Automatic Output feature is enabled or not. + This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset */ +} TIM_BDTRInitTypeDef; + +/* TIM_Output_Compare_and_PWM_modes */ +#define TIM_OCMode_Timing ((uint16_t)0x0000) +#define TIM_OCMode_Active ((uint16_t)0x0010) +#define TIM_OCMode_Inactive ((uint16_t)0x0020) +#define TIM_OCMode_Toggle ((uint16_t)0x0030) +#define TIM_OCMode_PWM1 ((uint16_t)0x0060) +#define TIM_OCMode_PWM2 ((uint16_t)0x0070) + +/* TIM_One_Pulse_Mode */ +#define TIM_OPMode_Single ((uint16_t)0x0008) +#define TIM_OPMode_Repetitive ((uint16_t)0x0000) + +/* TIM_Channel */ +#define TIM_Channel_1 ((uint16_t)0x0000) +#define TIM_Channel_2 ((uint16_t)0x0004) +#define TIM_Channel_3 ((uint16_t)0x0008) +#define TIM_Channel_4 ((uint16_t)0x000C) + +/* TIM_Clock_Division_CKD */ +#define TIM_CKD_DIV1 ((uint16_t)0x0000) +#define TIM_CKD_DIV2 ((uint16_t)0x0100) +#define TIM_CKD_DIV4 ((uint16_t)0x0200) + +/* TIM_Counter_Mode */ +#define TIM_CounterMode_Up ((uint16_t)0x0000) +#define TIM_CounterMode_Down ((uint16_t)0x0010) +#define TIM_CounterMode_CenterAligned1 ((uint16_t)0x0020) +#define TIM_CounterMode_CenterAligned2 ((uint16_t)0x0040) +#define TIM_CounterMode_CenterAligned3 ((uint16_t)0x0060) + +/* TIM_Output_Compare_Polarity */ +#define TIM_OCPolarity_High ((uint16_t)0x0000) +#define TIM_OCPolarity_Low ((uint16_t)0x0002) + +/* TIM_Output_Compare_N_Polarity */ +#define TIM_OCNPolarity_High ((uint16_t)0x0000) +#define TIM_OCNPolarity_Low ((uint16_t)0x0008) + +/* TIM_Output_Compare_state */ +#define TIM_OutputState_Disable ((uint16_t)0x0000) +#define TIM_OutputState_Enable ((uint16_t)0x0001) + +/* TIM_Output_Compare_N_state */ +#define TIM_OutputNState_Disable ((uint16_t)0x0000) +#define TIM_OutputNState_Enable ((uint16_t)0x0004) + +/* TIM_Capture_Compare_state */ +#define TIM_CCx_Enable ((uint16_t)0x0001) +#define TIM_CCx_Disable ((uint16_t)0x0000) + +/* TIM_Capture_Compare_N_state */ +#define TIM_CCxN_Enable ((uint16_t)0x0004) +#define TIM_CCxN_Disable ((uint16_t)0x0000) + +/* Break_Input_enable_disable */ +#define TIM_Break_Enable ((uint16_t)0x1000) +#define TIM_Break_Disable ((uint16_t)0x0000) + +/* Break_Polarity */ +#define TIM_BreakPolarity_Low ((uint16_t)0x0000) +#define TIM_BreakPolarity_High ((uint16_t)0x2000) + +/* TIM_AOE_Bit_Set_Reset */ +#define TIM_AutomaticOutput_Enable ((uint16_t)0x4000) +#define TIM_AutomaticOutput_Disable ((uint16_t)0x0000) + +/* Lock_level */ +#define TIM_LOCKLevel_OFF ((uint16_t)0x0000) +#define TIM_LOCKLevel_1 ((uint16_t)0x0100) +#define TIM_LOCKLevel_2 ((uint16_t)0x0200) +#define TIM_LOCKLevel_3 ((uint16_t)0x0300) + +/* OSSI_Off_State_Selection_for_Idle_mode_state */ +#define TIM_OSSIState_Enable ((uint16_t)0x0400) +#define TIM_OSSIState_Disable ((uint16_t)0x0000) + +/* OSSR_Off_State_Selection_for_Run_mode_state */ +#define TIM_OSSRState_Enable ((uint16_t)0x0800) +#define TIM_OSSRState_Disable ((uint16_t)0x0000) + +/* TIM_Output_Compare_Idle_State */ +#define TIM_OCIdleState_Set ((uint16_t)0x0100) +#define TIM_OCIdleState_Reset ((uint16_t)0x0000) + +/* TIM_Output_Compare_N_Idle_State */ +#define TIM_OCNIdleState_Set ((uint16_t)0x0200) +#define TIM_OCNIdleState_Reset ((uint16_t)0x0000) + +/* TIM_Input_Capture_Polarity */ +#define TIM_ICPolarity_Rising ((uint16_t)0x0000) +#define TIM_ICPolarity_Falling ((uint16_t)0x0002) +#define TIM_ICPolarity_BothEdge ((uint16_t)0x000A) + +/* TIM_Input_Capture_Selection */ +#define TIM_ICSelection_DirectTI ((uint16_t)0x0001) /* TIM Input 1, 2, 3 or 4 is selected to be + connected to IC1, IC2, IC3 or IC4, respectively */ +#define TIM_ICSelection_IndirectTI ((uint16_t)0x0002) /* TIM Input 1, 2, 3 or 4 is selected to be + connected to IC2, IC1, IC4 or IC3, respectively. */ +#define TIM_ICSelection_TRC ((uint16_t)0x0003) /* TIM Input 1, 2, 3 or 4 is selected to be connected to TRC. */ + +/* TIM_Input_Capture_Prescaler */ +#define TIM_ICPSC_DIV1 ((uint16_t)0x0000) /* Capture performed each time an edge is detected on the capture input. */ +#define TIM_ICPSC_DIV2 ((uint16_t)0x0004) /* Capture performed once every 2 events. */ +#define TIM_ICPSC_DIV4 ((uint16_t)0x0008) /* Capture performed once every 4 events. */ +#define TIM_ICPSC_DIV8 ((uint16_t)0x000C) /* Capture performed once every 8 events. */ + +/* TIM_interrupt_sources */ +#define TIM_IT_Update ((uint16_t)0x0001) +#define TIM_IT_CC1 ((uint16_t)0x0002) +#define TIM_IT_CC2 ((uint16_t)0x0004) +#define TIM_IT_CC3 ((uint16_t)0x0008) +#define TIM_IT_CC4 ((uint16_t)0x0010) +#define TIM_IT_COM ((uint16_t)0x0020) +#define TIM_IT_Trigger ((uint16_t)0x0040) +#define TIM_IT_Break ((uint16_t)0x0080) + +/* TIM_DMA_Base_address */ +#define TIM_DMABase_CR1 ((uint16_t)0x0000) +#define TIM_DMABase_CR2 ((uint16_t)0x0001) +#define TIM_DMABase_SMCR ((uint16_t)0x0002) +#define TIM_DMABase_DIER ((uint16_t)0x0003) +#define TIM_DMABase_SR ((uint16_t)0x0004) +#define TIM_DMABase_EGR ((uint16_t)0x0005) +#define TIM_DMABase_CCMR1 ((uint16_t)0x0006) +#define TIM_DMABase_CCMR2 ((uint16_t)0x0007) +#define TIM_DMABase_CCER ((uint16_t)0x0008) +#define TIM_DMABase_CNT ((uint16_t)0x0009) +#define TIM_DMABase_PSC ((uint16_t)0x000A) +#define TIM_DMABase_ARR ((uint16_t)0x000B) +#define TIM_DMABase_RCR ((uint16_t)0x000C) +#define TIM_DMABase_CCR1 ((uint16_t)0x000D) +#define TIM_DMABase_CCR2 ((uint16_t)0x000E) +#define TIM_DMABase_CCR3 ((uint16_t)0x000F) +#define TIM_DMABase_CCR4 ((uint16_t)0x0010) +#define TIM_DMABase_BDTR ((uint16_t)0x0011) +#define TIM_DMABase_DCR ((uint16_t)0x0012) + +/* TIM_DMA_Burst_Length */ +#define TIM_DMABurstLength_1Transfer ((uint16_t)0x0000) +#define TIM_DMABurstLength_2Transfers ((uint16_t)0x0100) +#define TIM_DMABurstLength_3Transfers ((uint16_t)0x0200) +#define TIM_DMABurstLength_4Transfers ((uint16_t)0x0300) +#define TIM_DMABurstLength_5Transfers ((uint16_t)0x0400) +#define TIM_DMABurstLength_6Transfers ((uint16_t)0x0500) +#define TIM_DMABurstLength_7Transfers ((uint16_t)0x0600) +#define TIM_DMABurstLength_8Transfers ((uint16_t)0x0700) +#define TIM_DMABurstLength_9Transfers ((uint16_t)0x0800) +#define TIM_DMABurstLength_10Transfers ((uint16_t)0x0900) +#define TIM_DMABurstLength_11Transfers ((uint16_t)0x0A00) +#define TIM_DMABurstLength_12Transfers ((uint16_t)0x0B00) +#define TIM_DMABurstLength_13Transfers ((uint16_t)0x0C00) +#define TIM_DMABurstLength_14Transfers ((uint16_t)0x0D00) +#define TIM_DMABurstLength_15Transfers ((uint16_t)0x0E00) +#define TIM_DMABurstLength_16Transfers ((uint16_t)0x0F00) +#define TIM_DMABurstLength_17Transfers ((uint16_t)0x1000) +#define TIM_DMABurstLength_18Transfers ((uint16_t)0x1100) + +/* TIM_DMA_sources */ +#define TIM_DMA_Update ((uint16_t)0x0100) +#define TIM_DMA_CC1 ((uint16_t)0x0200) +#define TIM_DMA_CC2 ((uint16_t)0x0400) +#define TIM_DMA_CC3 ((uint16_t)0x0800) +#define TIM_DMA_CC4 ((uint16_t)0x1000) +#define TIM_DMA_COM ((uint16_t)0x2000) +#define TIM_DMA_Trigger ((uint16_t)0x4000) + +/* TIM_External_Trigger_Prescaler */ +#define TIM_ExtTRGPSC_OFF ((uint16_t)0x0000) +#define TIM_ExtTRGPSC_DIV2 ((uint16_t)0x1000) +#define TIM_ExtTRGPSC_DIV4 ((uint16_t)0x2000) +#define TIM_ExtTRGPSC_DIV8 ((uint16_t)0x3000) + +/* TIM_Internal_Trigger_Selection */ +#define TIM_TS_ITR0 ((uint16_t)0x0000) +#define TIM_TS_ITR1 ((uint16_t)0x0010) +#define TIM_TS_ITR2 ((uint16_t)0x0020) +#define TIM_TS_ITR3 ((uint16_t)0x0030) +#define TIM_TS_TI1F_ED ((uint16_t)0x0040) +#define TIM_TS_TI1FP1 ((uint16_t)0x0050) +#define TIM_TS_TI2FP2 ((uint16_t)0x0060) +#define TIM_TS_ETRF ((uint16_t)0x0070) + +/* TIM_TIx_External_Clock_Source */ +#define TIM_TIxExternalCLK1Source_TI1 ((uint16_t)0x0050) +#define TIM_TIxExternalCLK1Source_TI2 ((uint16_t)0x0060) +#define TIM_TIxExternalCLK1Source_TI1ED ((uint16_t)0x0040) + +/* TIM_External_Trigger_Polarity */ +#define TIM_ExtTRGPolarity_Inverted ((uint16_t)0x8000) +#define TIM_ExtTRGPolarity_NonInverted ((uint16_t)0x0000) + +/* TIM_Prescaler_Reload_Mode */ +#define TIM_PSCReloadMode_Update ((uint16_t)0x0000) +#define TIM_PSCReloadMode_Immediate ((uint16_t)0x0001) + +/* TIM_Forced_Action */ +#define TIM_ForcedAction_Active ((uint16_t)0x0050) +#define TIM_ForcedAction_InActive ((uint16_t)0x0040) + +/* TIM_Encoder_Mode */ +#define TIM_EncoderMode_TI1 ((uint16_t)0x0001) +#define TIM_EncoderMode_TI2 ((uint16_t)0x0002) +#define TIM_EncoderMode_TI12 ((uint16_t)0x0003) + +/* TIM_Event_Source */ +#define TIM_EventSource_Update ((uint16_t)0x0001) +#define TIM_EventSource_CC1 ((uint16_t)0x0002) +#define TIM_EventSource_CC2 ((uint16_t)0x0004) +#define TIM_EventSource_CC3 ((uint16_t)0x0008) +#define TIM_EventSource_CC4 ((uint16_t)0x0010) +#define TIM_EventSource_COM ((uint16_t)0x0020) +#define TIM_EventSource_Trigger ((uint16_t)0x0040) +#define TIM_EventSource_Break ((uint16_t)0x0080) + +/* TIM_Update_Source */ +#define TIM_UpdateSource_Global ((uint16_t)0x0000) /* Source of update is the counter overflow/underflow + or the setting of UG bit, or an update generation + through the slave mode controller. */ +#define TIM_UpdateSource_Regular ((uint16_t)0x0001) /* Source of update is counter overflow/underflow. */ + +/* TIM_Output_Compare_Preload_State */ +#define TIM_OCPreload_Enable ((uint16_t)0x0008) +#define TIM_OCPreload_Disable ((uint16_t)0x0000) + +/* TIM_Output_Compare_Fast_State */ +#define TIM_OCFast_Enable ((uint16_t)0x0004) +#define TIM_OCFast_Disable ((uint16_t)0x0000) + +/* TIM_Output_Compare_Clear_State */ +#define TIM_OCClear_Enable ((uint16_t)0x0080) +#define TIM_OCClear_Disable ((uint16_t)0x0000) + +/* TIM_Trigger_Output_Source */ +#define TIM_TRGOSource_Reset ((uint16_t)0x0000) +#define TIM_TRGOSource_Enable ((uint16_t)0x0010) +#define TIM_TRGOSource_Update ((uint16_t)0x0020) +#define TIM_TRGOSource_OC1 ((uint16_t)0x0030) +#define TIM_TRGOSource_OC1Ref ((uint16_t)0x0040) +#define TIM_TRGOSource_OC2Ref ((uint16_t)0x0050) +#define TIM_TRGOSource_OC3Ref ((uint16_t)0x0060) +#define TIM_TRGOSource_OC4Ref ((uint16_t)0x0070) + +/* TIM_Slave_Mode */ +#define TIM_SlaveMode_Reset ((uint16_t)0x0004) +#define TIM_SlaveMode_Gated ((uint16_t)0x0005) +#define TIM_SlaveMode_Trigger ((uint16_t)0x0006) +#define TIM_SlaveMode_External1 ((uint16_t)0x0007) + +/* TIM_Master_Slave_Mode */ +#define TIM_MasterSlaveMode_Enable ((uint16_t)0x0080) +#define TIM_MasterSlaveMode_Disable ((uint16_t)0x0000) + +/* TIM_Flags */ +#define TIM_FLAG_Update ((uint16_t)0x0001) +#define TIM_FLAG_CC1 ((uint16_t)0x0002) +#define TIM_FLAG_CC2 ((uint16_t)0x0004) +#define TIM_FLAG_CC3 ((uint16_t)0x0008) +#define TIM_FLAG_CC4 ((uint16_t)0x0010) +#define TIM_FLAG_COM ((uint16_t)0x0020) +#define TIM_FLAG_Trigger ((uint16_t)0x0040) +#define TIM_FLAG_Break ((uint16_t)0x0080) +#define TIM_FLAG_CC1OF ((uint16_t)0x0200) +#define TIM_FLAG_CC2OF ((uint16_t)0x0400) +#define TIM_FLAG_CC3OF ((uint16_t)0x0800) +#define TIM_FLAG_CC4OF ((uint16_t)0x1000) + +/* TIM_Legacy */ +#define TIM_DMABurstLength_1Byte TIM_DMABurstLength_1Transfer +#define TIM_DMABurstLength_2Bytes TIM_DMABurstLength_2Transfers +#define TIM_DMABurstLength_3Bytes TIM_DMABurstLength_3Transfers +#define TIM_DMABurstLength_4Bytes TIM_DMABurstLength_4Transfers +#define TIM_DMABurstLength_5Bytes TIM_DMABurstLength_5Transfers +#define TIM_DMABurstLength_6Bytes TIM_DMABurstLength_6Transfers +#define TIM_DMABurstLength_7Bytes TIM_DMABurstLength_7Transfers +#define TIM_DMABurstLength_8Bytes TIM_DMABurstLength_8Transfers +#define TIM_DMABurstLength_9Bytes TIM_DMABurstLength_9Transfers +#define TIM_DMABurstLength_10Bytes TIM_DMABurstLength_10Transfers +#define TIM_DMABurstLength_11Bytes TIM_DMABurstLength_11Transfers +#define TIM_DMABurstLength_12Bytes TIM_DMABurstLength_12Transfers +#define TIM_DMABurstLength_13Bytes TIM_DMABurstLength_13Transfers +#define TIM_DMABurstLength_14Bytes TIM_DMABurstLength_14Transfers +#define TIM_DMABurstLength_15Bytes TIM_DMABurstLength_15Transfers +#define TIM_DMABurstLength_16Bytes TIM_DMABurstLength_16Transfers +#define TIM_DMABurstLength_17Bytes TIM_DMABurstLength_17Transfers +#define TIM_DMABurstLength_18Bytes TIM_DMABurstLength_18Transfers + + +void TIM_DeInit(TIM_TypeDef* TIMx); +void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); +void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); +void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); +void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); +void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); +void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct); +void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct); +void TIM_BDTRConfig(TIM_TypeDef* TIMx, TIM_BDTRInitTypeDef *TIM_BDTRInitStruct); +void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); +void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct); +void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct); +void TIM_BDTRStructInit(TIM_BDTRInitTypeDef* TIM_BDTRInitStruct); +void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); +void TIM_GenerateEvent(TIM_TypeDef* TIMx, uint16_t TIM_EventSource); +void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength); +void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource, FunctionalState NewState); +void TIM_InternalClockConfig(TIM_TypeDef* TIMx); +void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); +void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource, + uint16_t TIM_ICPolarity, uint16_t ICFilter); +void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter); +void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter); +void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter); +void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode); +void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode); +void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); +void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode, + uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity); +void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); +void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); +void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); +void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); +void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_SelectCOM(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_SelectCCDMA(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_CCPreloadControl(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); +void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); +void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); +void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); +void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); +void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); +void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); +void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); +void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); +void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); +void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); +void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); +void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); +void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity); +void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); +void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity); +void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); +void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity); +void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); +void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx); +void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN); +void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode); +void TIM_UpdateDisableConfig(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_UpdateRequestConfig(TIM_TypeDef* TIMx, uint16_t TIM_UpdateSource); +void TIM_SelectHallSensor(TIM_TypeDef* TIMx, FunctionalState NewState); +void TIM_SelectOnePulseMode(TIM_TypeDef* TIMx, uint16_t TIM_OPMode); +void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource); +void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode); +void TIM_SelectMasterSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_MasterSlaveMode); +void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter); +void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload); +void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1); +void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2); +void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3); +void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4); +void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); +void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); +void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); +void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); +void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD); +uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx); +uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx); +uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx); +uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx); +uint16_t TIM_GetCounter(TIM_TypeDef* TIMx); +uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx); +FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); +void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); +ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT); +void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + + + + diff --git a/demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x_usart.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_usart.h similarity index 100% rename from demo/ch32/ch32v307/SRC/Peripheral/inc/ch32v30x_usart.h rename to demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_usart.h diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_wwdg.h b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_wwdg.h new file mode 100644 index 00000000..55414b00 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/inc/ch32v30x_wwdg.h @@ -0,0 +1,40 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_wwdg.h +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file contains all the functions prototypes for the WWDG +* firmware library. +*******************************************************************************/ +#ifndef __CH32V30x_WWDG_H +#define __CH32V30x_WWDG_H + +#ifdef __cplusplus + extern "C" { +#endif + +#include "ch32v30x.h" + + +/* WWDG_Prescaler */ +#define WWDG_Prescaler_1 ((uint32_t)0x00000000) +#define WWDG_Prescaler_2 ((uint32_t)0x00000080) +#define WWDG_Prescaler_4 ((uint32_t)0x00000100) +#define WWDG_Prescaler_8 ((uint32_t)0x00000180) + + +void WWDG_DeInit(void); +void WWDG_SetPrescaler(uint32_t WWDG_Prescaler); +void WWDG_SetWindowValue(uint8_t WindowValue); +void WWDG_EnableIT(void); +void WWDG_SetCounter(uint8_t Counter); +void WWDG_Enable(uint8_t Counter); +FlagStatus WWDG_GetFlagStatus(void); +void WWDG_ClearFlag(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_adc.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_adc.c new file mode 100644 index 00000000..ab1b05d1 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_adc.c @@ -0,0 +1,1094 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_adc.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the ADC firmware functions. +*******************************************************************************/ +#include "ch32v30x_adc.h" +#include "ch32v30x_rcc.h" + +/* ADC DISCNUM mask */ +#define CTLR1_DISCNUM_Reset ((uint32_t)0xFFFF1FFF) + +/* ADC DISCEN mask */ +#define CTLR1_DISCEN_Set ((uint32_t)0x00000800) +#define CTLR1_DISCEN_Reset ((uint32_t)0xFFFFF7FF) + +/* ADC JAUTO mask */ +#define CTLR1_JAUTO_Set ((uint32_t)0x00000400) +#define CTLR1_JAUTO_Reset ((uint32_t)0xFFFFFBFF) + +/* ADC JDISCEN mask */ +#define CTLR1_JDISCEN_Set ((uint32_t)0x00001000) +#define CTLR1_JDISCEN_Reset ((uint32_t)0xFFFFEFFF) + +/* ADC AWDCH mask */ +#define CTLR1_AWDCH_Reset ((uint32_t)0xFFFFFFE0) + +/* ADC Analog watchdog enable mode mask */ +#define CTLR1_AWDMode_Reset ((uint32_t)0xFF3FFDFF) + +/* CTLR1 register Mask */ +#define CTLR1_CLEAR_Mask ((uint32_t)0xE0F0FEFF) + +/* ADC ADON mask */ +#define CTLR2_ADON_Set ((uint32_t)0x00000001) +#define CTLR2_ADON_Reset ((uint32_t)0xFFFFFFFE) + +/* ADC DMA mask */ +#define CTLR2_DMA_Set ((uint32_t)0x00000100) +#define CTLR2_DMA_Reset ((uint32_t)0xFFFFFEFF) + +/* ADC RSTCAL mask */ +#define CTLR2_RSTCAL_Set ((uint32_t)0x00000008) + +/* ADC CAL mask */ +#define CTLR2_CAL_Set ((uint32_t)0x00000004) + +/* ADC SWSTART mask */ +#define CTLR2_SWSTART_Set ((uint32_t)0x00400000) + +/* ADC EXTTRIG mask */ +#define CTLR2_EXTTRIG_Set ((uint32_t)0x00100000) +#define CTLR2_EXTTRIG_Reset ((uint32_t)0xFFEFFFFF) + +/* ADC Software start mask */ +#define CTLR2_EXTTRIG_SWSTART_Set ((uint32_t)0x00500000) +#define CTLR2_EXTTRIG_SWSTART_Reset ((uint32_t)0xFFAFFFFF) + +/* ADC JEXTSEL mask */ +#define CTLR2_JEXTSEL_Reset ((uint32_t)0xFFFF8FFF) + +/* ADC JEXTTRIG mask */ +#define CTLR2_JEXTTRIG_Set ((uint32_t)0x00008000) +#define CTLR2_JEXTTRIG_Reset ((uint32_t)0xFFFF7FFF) + +/* ADC JSWSTART mask */ +#define CTLR2_JSWSTART_Set ((uint32_t)0x00200000) + +/* ADC injected software start mask */ +#define CTLR2_JEXTTRIG_JSWSTART_Set ((uint32_t)0x00208000) +#define CTLR2_JEXTTRIG_JSWSTART_Reset ((uint32_t)0xFFDF7FFF) + +/* ADC TSPD mask */ +#define CTLR2_TSVREFE_Set ((uint32_t)0x00800000) +#define CTLR2_TSVREFE_Reset ((uint32_t)0xFF7FFFFF) + +/* CTLR2 register Mask */ +#define CTLR2_CLEAR_Mask ((uint32_t)0xFFF1F7FD) + +/* ADC SQx mask */ +#define RSQR3_SQ_Set ((uint32_t)0x0000001F) +#define RSQR2_SQ_Set ((uint32_t)0x0000001F) +#define RSQR1_SQ_Set ((uint32_t)0x0000001F) + +/* RSQR1 register Mask */ +#define RSQR1_CLEAR_Mask ((uint32_t)0xFF0FFFFF) + +/* ADC JSQx mask */ +#define ISQR_JSQ_Set ((uint32_t)0x0000001F) + +/* ADC JL mask */ +#define ISQR_JL_Set ((uint32_t)0x00300000) +#define ISQR_JL_Reset ((uint32_t)0xFFCFFFFF) + +/* ADC SMPx mask */ +#define SAMPTR1_SMP_Set ((uint32_t)0x00000007) +#define SAMPTR2_SMP_Set ((uint32_t)0x00000007) + +/* ADC IDATARx registers offset */ +#define IDATAR_Offset ((uint8_t)0x28) + +/* ADC1 RDATAR register base address */ +#define RDATAR_ADDRESS ((uint32_t)0x4001244C) + +/******************************************************************************* +* Function Name : ADC_DeInit +* Description : Deinitializes the ADCx peripheral registers to their default +* reset values. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Return : None +*******************************************************************************/ +void ADC_DeInit(ADC_TypeDef* ADCx) +{ + if (ADCx == ADC1) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE); + } + else if(ADCx == ADC2) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2, DISABLE); + } +} + +/******************************************************************************* +* Function Name : ADC_Init +* Description : Initializes the ADCx peripheral according to the specified +* parameters in the ADC_InitStruct. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_InitStruct: pointer to an ADC_InitTypeDef structure that +* contains the configuration information for the specified ADC peripheral. +* Return : None +*******************************************************************************/ +void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct) +{ + uint32_t tmpreg1 = 0; + uint8_t tmpreg2 = 0; + + tmpreg1 = ADCx->CTLR1; + tmpreg1 &= CTLR1_CLEAR_Mask; + tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_Mode | (uint32_t) ADC_InitStruct->ADC_OutputBuffer | + (uint32_t) ADC_InitStruct->ADC_Pga | ((uint32_t)ADC_InitStruct->ADC_ScanConvMode << 8)); + ADCx->CTLR1 = tmpreg1; + + tmpreg1 = ADCx->CTLR2; + tmpreg1 &= CTLR2_CLEAR_Mask; + tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_DataAlign | ADC_InitStruct->ADC_ExternalTrigConv | + ((uint32_t)ADC_InitStruct->ADC_ContinuousConvMode << 1)); + ADCx->CTLR2 = tmpreg1; + + tmpreg1 = ADCx->RSQR1; + tmpreg1 &= RSQR1_CLEAR_Mask; + tmpreg2 |= (uint8_t) (ADC_InitStruct->ADC_NbrOfChannel - (uint8_t)1); + tmpreg1 |= (uint32_t)tmpreg2 << 20; + ADCx->RSQR1 = tmpreg1; +} + +/******************************************************************************* +* Function Name : ADC_StructInit +* Description : Fills each ADC_InitStruct member with its default value. +* Input : ADC_InitStruct : pointer to an ADC_InitTypeDef structure that +* contains the configuration information for the specified ADC peripheral. +* Return : None +*******************************************************************************/ +void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct) +{ + ADC_InitStruct->ADC_Mode = ADC_Mode_Independent; + ADC_InitStruct->ADC_ScanConvMode = DISABLE; + ADC_InitStruct->ADC_ContinuousConvMode = DISABLE; + ADC_InitStruct->ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; + ADC_InitStruct->ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStruct->ADC_NbrOfChannel = 1; +} + +/******************************************************************************* +* Function Name : ADC_Cmd +* Description : Enables or disables the specified ADC peripheral. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADCx->CTLR2 |= CTLR2_ADON_Set; + } + else + { + ADCx->CTLR2 &= CTLR2_ADON_Reset; + } +} + +/******************************************************************************* +* Function Name : ADC_DMACmd +* Description : Enables or disables the specified ADC DMA request. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADCx->CTLR2 |= CTLR2_DMA_Set; + } + else + { + ADCx->CTLR2 &= CTLR2_DMA_Reset; + } +} + +/******************************************************************************* +* Function Name : ADC_ITConfig +* Description : Enables or disables the specified ADC interrupts. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_IT: specifies the ADC interrupt sources to be enabled or disabled. +* ADC_IT_EOC: End of conversion interrupt mask. +* ADC_IT_AWD: Analog watchdog interrupt mask. +* ADC_IT_JEOC: End of injected conversion interrupt mask. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState) +{ + uint8_t itmask = 0; + + itmask = (uint8_t)ADC_IT; + + if (NewState != DISABLE) + { + ADCx->CTLR1 |= itmask; + } + else + { + ADCx->CTLR1 &= (~(uint32_t)itmask); + } +} + +/******************************************************************************* +* Function Name : ADC_ResetCalibration +* Description : Resets the selected ADC calibration registers. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Return : None +*******************************************************************************/ +void ADC_ResetCalibration(ADC_TypeDef* ADCx) +{ + ADCx->CTLR2 |= CTLR2_RSTCAL_Set; +} + +/******************************************************************************* +* Function Name : ADC_GetResetCalibrationStatus +* Description : Gets the selected ADC reset calibration registers status. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + + if ((ADCx->CTLR2 & CTLR2_RSTCAL_Set) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ADC_StartCalibration +* Description : Starts the selected ADC calibration process. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Return : None +*******************************************************************************/ +void ADC_StartCalibration(ADC_TypeDef* ADCx) +{ + ADCx->CTLR2 |= CTLR2_CAL_Set; +} + +/******************************************************************************* +* Function Name : ADC_GetCalibrationStatus +* Description : Gets the selected ADC calibration status. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + + if ((ADCx->CTLR2 & CTLR2_CAL_Set) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ADC_SoftwareStartConvCmd +* Description : Enables or disables the selected ADC software start conversion. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADCx->CTLR2 |= CTLR2_EXTTRIG_SWSTART_Set; + } + else + { + ADCx->CTLR2 &= CTLR2_EXTTRIG_SWSTART_Reset; + } +} + +/******************************************************************************* +* Function Name : ADC_GetSoftwareStartConvStatus +* Description : Gets the selected ADC Software start conversion Status. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + + if ((ADCx->CTLR2 & CTLR2_SWSTART_Set) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ADC_DiscModeChannelCountConfig +* Description : Configures the discontinuous mode for the selected ADC regular +* group channel. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Number: specifies the discontinuous mode regular channel +* count value. +* This number must be between 1 and 8. +* Return : None +*******************************************************************************/ +void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + + tmpreg1 = ADCx->CTLR1; + tmpreg1 &= CTLR1_DISCNUM_Reset; + tmpreg2 = Number - 1; + tmpreg1 |= tmpreg2 << 13; + ADCx->CTLR1 = tmpreg1; +} + +/******************************************************************************* +* Function Name : ADC_DiscModeCmd +* Description : Enables or disables the discontinuous mode on regular group +* channel for the specified ADC. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADCx->CTLR1 |= CTLR1_DISCEN_Set; + } + else + { + ADCx->CTLR1 &= CTLR1_DISCEN_Reset; + } +} + +/******************************************************************************* +* Function Name : ADC_RegularChannelConfig +* Description : Configures for the selected ADC regular channel its corresponding +* rank in the sequencer and its sample time. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_Channel: the ADC channel to configure. +* ADC_Channel_0: ADC Channel0 selected. +* ADC_Channel_1: ADC Channel1 selected. +* ADC_Channel_2: ADC Channel2 selected. +* ADC_Channel_3: ADC Channel3 selected. +* ADC_Channel_4: ADC Channel4 selected. +* ADC_Channel_5: ADC Channel5 selected. +* ADC_Channel_6: ADC Channel6 selected. +* ADC_Channel_7: ADC Channel7 selected. +* ADC_Channel_8: ADC Channel8 selected. +* ADC_Channel_9: ADC Channel9 selected. +* ADC_Channel_10: ADC Channel10 selected. +* ADC_Channel_11: ADC Channel11 selected. +* ADC_Channel_12: ADC Channel12 selected. +* ADC_Channel_13: ADC Channel13 selected. +* ADC_Channel_14: ADC Channel14 selected. +* ADC_Channel_15: ADC Channel15 selected. +* ADC_Channel_16: ADC Channel16 selected. +* ADC_Channel_17: ADC Channel17 selected. +* Rank: The rank in the regular group sequencer. +* This parameter must be between 1 to 16. +* ADC_SampleTime: The sample time value to be set for the selected channel. +* ADC_SampleTime_1Cycles5: Sample time equal to 1.5 cycles. +* ADC_SampleTime_7Cycles5: Sample time equal to 7.5 cycles. +* ADC_SampleTime_13Cycles5: Sample time equal to 13.5 cycles. +* ADC_SampleTime_28Cycles5: Sample time equal to 28.5 cycles. +* ADC_SampleTime_41Cycles5: Sample time equal to 41.5 cycles. +* ADC_SampleTime_55Cycles5: Sample time equal to 55.5 cycles. +* ADC_SampleTime_71Cycles5: Sample time equal to 71.5 cycles. +* ADC_SampleTime_239Cycles5: Sample time equal to 239.5 cycles. +* Return : None +*******************************************************************************/ +void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + + if (ADC_Channel > ADC_Channel_9) + { + tmpreg1 = ADCx->SAMPTR1; + tmpreg2 = SAMPTR1_SMP_Set << (3 * (ADC_Channel - 10)); + tmpreg1 &= ~tmpreg2; + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10)); + tmpreg1 |= tmpreg2; + ADCx->SAMPTR1 = tmpreg1; + } + else + { + tmpreg1 = ADCx->SAMPTR2; + tmpreg2 = SAMPTR2_SMP_Set << (3 * ADC_Channel); + tmpreg1 &= ~tmpreg2; + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + tmpreg1 |= tmpreg2; + ADCx->SAMPTR2 = tmpreg1; + } + + if (Rank < 7) + { + tmpreg1 = ADCx->RSQR3; + tmpreg2 = RSQR3_SQ_Set << (5 * (Rank - 1)); + tmpreg1 &= ~tmpreg2; + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1)); + tmpreg1 |= tmpreg2; + ADCx->RSQR3 = tmpreg1; + } + else if (Rank < 13) + { + tmpreg1 = ADCx->RSQR2; + tmpreg2 = RSQR2_SQ_Set << (5 * (Rank - 7)); + tmpreg1 &= ~tmpreg2; + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7)); + tmpreg1 |= tmpreg2; + ADCx->RSQR2 = tmpreg1; + } + else + { + tmpreg1 = ADCx->RSQR1; + tmpreg2 = RSQR1_SQ_Set << (5 * (Rank - 13)); + tmpreg1 &= ~tmpreg2; + tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13)); + tmpreg1 |= tmpreg2; + ADCx->RSQR1 = tmpreg1; + } +} + +/******************************************************************************* +* Function Name : ADC_ExternalTrigConvCmd +* Description : Enables or disables the ADCx conversion through external trigger. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADCx->CTLR2 |= CTLR2_EXTTRIG_Set; + } + else + { + ADCx->CTLR2 &= CTLR2_EXTTRIG_Reset; + } +} + +/******************************************************************************* +* Function Name : ADC_GetConversionValue +* Description : Returns the last ADCx conversion result data for regular channel. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Return : ADCx->RDATAR: +* The Data conversion value. +*******************************************************************************/ +uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx) +{ + return (uint16_t) ADCx->RDATAR; +} + +/******************************************************************************* +* Function Name : ADC_GetDualModeConversionValue +* Description : Returns the last ADC1 and ADC2 conversion result data in dual mode. +* Input : None +* Return : RDATAR_ADDRESS: +* The Data conversion value. +*******************************************************************************/ +uint32_t ADC_GetDualModeConversionValue(void) +{ + return (*(__IO uint32_t *) RDATAR_ADDRESS); +} + +/******************************************************************************* +* Function Name : ADC_AutoInjectedConvCmd +* Description : Enables or disables the selected ADC automatic injected group +* conversion after regular one. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADCx->CTLR1 |= CTLR1_JAUTO_Set; + } + else + { + ADCx->CTLR1 &= CTLR1_JAUTO_Reset; + } +} + +/******************************************************************************* +* Function Name : ADC_InjectedDiscModeCmd +* Description : Enables or disables the discontinuous mode for injected group +* channel for the specified ADC. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADCx->CTLR1 |= CTLR1_JDISCEN_Set; + } + else + { + ADCx->CTLR1 &= CTLR1_JDISCEN_Reset; + } +} + +/******************************************************************************* +* Function Name : ADC_ExternalTrigInjectedConvConfig +* Description : Configures the ADCx external trigger for injected channels conversion. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_ExternalTrigInjecConv: specifies the ADC trigger to start +* injected conversion. +* ADC_ExternalTrigInjecConv_T1_TRGO: Timer1 TRGO event selected. +* ADC_ExternalTrigInjecConv_T1_CC4: Timer1 capture compare4 selected. +* ADC_ExternalTrigInjecConv_T2_TRGO: Timer2 TRGO event selected. +* ADC_ExternalTrigInjecConv_T2_CC1: Timer2 capture compare1 selected. +* ADC_ExternalTrigInjecConv_T3_CC4: Timer3 capture compare4 selected. +* ADC_ExternalTrigInjecConv_T4_TRGO: Timer4 TRGO event selected. +* ADC_ExternalTrigInjecConv_Ext_IT15_TIM8_CC4: External interrupt +* line 15 event selected. +* ADC_ExternalTrigInjecConv_None: Injected conversion started +* by software and not by external trigger. +* Return : None +*******************************************************************************/ +void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv) +{ + uint32_t tmpreg = 0; + + tmpreg = ADCx->CTLR2; + tmpreg &= CTLR2_JEXTSEL_Reset; + tmpreg |= ADC_ExternalTrigInjecConv; + ADCx->CTLR2 = tmpreg; +} + +/******************************************************************************* +* Function Name : ADC_ExternalTrigInjectedConvCmd +* Description : Enables or disables the ADCx injected channels conversion through +* external trigger. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADCx->CTLR2 |= CTLR2_JEXTTRIG_Set; + } + else + { + ADCx->CTLR2 &= CTLR2_JEXTTRIG_Reset; + } +} + +/******************************************************************************* +* Function Name : ADC_SoftwareStartInjectedConvCmd +* Description : Enables or disables the selected ADC start of the injected +* channels conversion. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADCx->CTLR2 |= CTLR2_JEXTTRIG_JSWSTART_Set; + } + else + { + ADCx->CTLR2 &= CTLR2_JEXTTRIG_JSWSTART_Reset; + } +} + +/******************************************************************************* +* Function Name : ADC_GetSoftwareStartInjectedConvCmdStatus +* Description : Gets the selected ADC Software start injected conversion Status. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx) +{ + FlagStatus bitstatus = RESET; + + if ((ADCx->CTLR2 & CTLR2_JSWSTART_Set) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ADC_InjectedChannelConfig +* Description : Configures for the selected ADC injected channel its corresponding +* rank in the sequencer and its sample time. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_Channel: the ADC channel to configure. +* ADC_Channel_0: ADC Channel0 selected. +* ADC_Channel_1: ADC Channel1 selected. +* ADC_Channel_2: ADC Channel2 selected. +* ADC_Channel_3: ADC Channel3 selected. +* ADC_Channel_4: ADC Channel4 selected. +* ADC_Channel_5: ADC Channel5 selected. +* ADC_Channel_6: ADC Channel6 selected. +* ADC_Channel_7: ADC Channel7 selected. +* ADC_Channel_8: ADC Channel8 selected. +* ADC_Channel_9: ADC Channel9 selected. +* ADC_Channel_10: ADC Channel10 selected. +* ADC_Channel_11: ADC Channel11 selected. +* ADC_Channel_12: ADC Channel12 selected. +* ADC_Channel_13: ADC Channel13 selected. +* ADC_Channel_14: ADC Channel14 selected. +* ADC_Channel_15: ADC Channel15 selected. +* ADC_Channel_16: ADC Channel16 selected. +* ADC_Channel_17: ADC Channel17 selected. +* Rank: The rank in the injected group sequencer. +* This parameter must be between 1 to 4. +* ADC_SampleTime: The sample time value to be set for the selected channel. +* ADC_SampleTime_1Cycles5: Sample time equal to 1.5 cycles. +* ADC_SampleTime_7Cycles5: Sample time equal to 7.5 cycles. +* ADC_SampleTime_13Cycles5: Sample time equal to 13.5 cycles. +* ADC_SampleTime_28Cycles5: Sample time equal to 28.5 cycles. +* ADC_SampleTime_41Cycles5: Sample time equal to 41.5 cycles. +* ADC_SampleTime_55Cycles5: Sample time equal to 55.5 cycles. +* ADC_SampleTime_71Cycles5: Sample time equal to 71.5 cycles. +* ADC_SampleTime_239Cycles5: Sample time equal to 239.5 cycles. +* Return : None +*******************************************************************************/ +void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0; + + if (ADC_Channel > ADC_Channel_9) + { + tmpreg1 = ADCx->SAMPTR1; + tmpreg2 = SAMPTR1_SMP_Set << (3*(ADC_Channel - 10)); + tmpreg1 &= ~tmpreg2; + tmpreg2 = (uint32_t)ADC_SampleTime << (3*(ADC_Channel - 10)); + tmpreg1 |= tmpreg2; + ADCx->SAMPTR1 = tmpreg1; + } + else + { + tmpreg1 = ADCx->SAMPTR2; + tmpreg2 = SAMPTR2_SMP_Set << (3 * ADC_Channel); + tmpreg1 &= ~tmpreg2; + tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel); + tmpreg1 |= tmpreg2; + ADCx->SAMPTR2 = tmpreg1; + } + + tmpreg1 = ADCx->ISQR; + tmpreg3 = (tmpreg1 & ISQR_JL_Set)>> 20; + tmpreg2 = ISQR_JSQ_Set << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + tmpreg1 &= ~tmpreg2; + tmpreg2 = (uint32_t)ADC_Channel << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1))); + tmpreg1 |= tmpreg2; + ADCx->ISQR = tmpreg1; +} + +/******************************************************************************* +* Function Name : ADC_InjectedSequencerLengthConfig +* Description : Configures the sequencer length for injected channels. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Length: The sequencer length. +* This parameter must be a number between 1 to 4. +* Return : None +*******************************************************************************/ +void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length) +{ + uint32_t tmpreg1 = 0; + uint32_t tmpreg2 = 0; + + tmpreg1 = ADCx->ISQR; + tmpreg1 &= ISQR_JL_Reset; + tmpreg2 = Length - 1; + tmpreg1 |= tmpreg2 << 20; + ADCx->ISQR = tmpreg1; +} + +/******************************************************************************* +* Function Name : ADC_SetInjectedOffset +* Description : Set the injected channels conversion value offset. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_InjectedChannel: the ADC injected channel to set its offset. +* ADC_InjectedChannel_1: Injected Channel1 selected. +* ADC_InjectedChannel_2: Injected Channel2 selected. +* ADC_InjectedChannel_3: Injected Channel3 selected. +* ADC_InjectedChannel_4: Injected Channel4 selected. +* Offset: the offset value for the selected ADC injected channel. +* This parameter must be a 12bit value. +* Return : None +*******************************************************************************/ +void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset) +{ + __IO uint32_t tmp = 0; + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel; + + *(__IO uint32_t *) tmp = (uint32_t)Offset; +} + +/******************************************************************************* +* Function Name : ADC_GetInjectedConversionValue +* Description : Returns the ADC injected channel conversion result. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_InjectedChannel: the converted ADC injected channel. +* ADC_InjectedChannel_1: Injected Channel1 selected. +* ADC_InjectedChannel_2: Injected Channel2 selected. +* ADC_InjectedChannel_3: Injected Channel3 selected. +* ADC_InjectedChannel_4: Injected Channel4 selected. +* Return : tmp: The Data conversion value. +*******************************************************************************/ +uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel) +{ + __IO uint32_t tmp = 0; + + tmp = (uint32_t)ADCx; + tmp += ADC_InjectedChannel + IDATAR_Offset; + + return (uint16_t) (*(__IO uint32_t*) tmp); +} + +/******************************************************************************* +* Function Name : ADC_AnalogWatchdogCmd +* Description : Enables or disables the analog watchdog on single/all regular +* or injected channels. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_AnalogWatchdog: the ADC analog watchdog configuration. +* ADC_AnalogWatchdog_SingleRegEnable: Analog watchdog on a +* single regular channel. +* ADC_AnalogWatchdog_SingleInjecEnable: Analog watchdog on a +* single injected channel. +* ADC_AnalogWatchdog_SingleRegOrInjecEnable: Analog watchdog +* on a single regular or injected channel. +* ADC_AnalogWatchdog_AllRegEnable: Analog watchdog on all +* regular channel. +* ADC_AnalogWatchdog_AllInjecEnable: Analog watchdog on all +* injected channel. +* ADC_AnalogWatchdog_AllRegAllInjecEnable: Analog watchdog on +* all regular and injected channels. +* ADC_AnalogWatchdog_None: No channel guarded by the analog +* watchdog. +* Return : None +*******************************************************************************/ +void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog) +{ + uint32_t tmpreg = 0; + + tmpreg = ADCx->CTLR1; + tmpreg &= CTLR1_AWDMode_Reset; + tmpreg |= ADC_AnalogWatchdog; + ADCx->CTLR1 = tmpreg; +} + +/******************************************************************************* +* Function Name : ADC_AnalogWatchdogThresholdsConfig +* Description : Configures the high and low thresholds of the analog watchdog. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* HighThreshold: the ADC analog watchdog High threshold value. +* This parameter must be a 12bit value. +* LowThreshold: the ADC analog watchdog Low threshold value. +* This parameter must be a 12bit value. +* Return : None +*******************************************************************************/ +void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, + uint16_t LowThreshold) +{ + ADCx->WDHTR = HighThreshold; + ADCx->WDLTR = LowThreshold; +} + +/******************************************************************************* +* Function Name : ADC_AnalogWatchdogSingleChannelConfig +* Description : Configures the analog watchdog guarded single channel. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_Channel: the ADC channel to configure for the analog watchdog. +* ADC_Channel_0: ADC Channel0 selected. +* ADC_Channel_1: ADC Channel1 selected. +* ADC_Channel_2: ADC Channel2 selected. +* ADC_Channel_3: ADC Channel3 selected. +* ADC_Channel_4: ADC Channel4 selected. +* ADC_Channel_5: ADC Channel5 selected. +* ADC_Channel_6: ADC Channel6 selected. +* ADC_Channel_7: ADC Channel7 selected. +* ADC_Channel_8: ADC Channel8 selected. +* ADC_Channel_9: ADC Channel9 selected. +* ADC_Channel_10: ADC Channel10 selected. +* ADC_Channel_11: ADC Channel11 selected. +* ADC_Channel_12: ADC Channel12 selected. +* ADC_Channel_13: ADC Channel13 selected. +* ADC_Channel_14: ADC Channel14 selected. +* ADC_Channel_15: ADC Channel15 selected. +* ADC_Channel_16: ADC Channel16 selected. +* ADC_Channel_17: ADC Channel17 selected. +* Return : None +*******************************************************************************/ +void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel) +{ + uint32_t tmpreg = 0; + + tmpreg = ADCx->CTLR1; + tmpreg &= CTLR1_AWDCH_Reset; + tmpreg |= ADC_Channel; + ADCx->CTLR1 = tmpreg; +} + +/******************************************************************************* +* Function Name : ADC_TempSensorVrefintCmd +* Description : Enables or disables the temperature sensor and Vrefint channel. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_TempSensorVrefintCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADC1->CTLR2 |= CTLR2_TSVREFE_Set; + } + else + { + ADC1->CTLR2 &= CTLR2_TSVREFE_Reset; + } +} + +/******************************************************************************* +* Function Name : ADC_GetFlagStatus +* Description : Checks whether the specified ADC flag is set or not. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_FLAG: specifies the flag to check. +* ADC_FLAG_AWD: Analog watchdog flag. +* ADC_FLAG_EOC: End of conversion flag. +* ADC_FLAG_JEOC: End of injected group conversion flag. +* ADC_FLAG_JSTRT: Start of injected group conversion flag. +* ADC_FLAG_STRT: Start of regular group conversion flag. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) +{ + FlagStatus bitstatus = RESET; + + if ((ADCx->STATR & ADC_FLAG) != (uint8_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ADC_ClearFlag +* Description : Clears the ADCx's pending flags. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_FLAG: specifies the flag to clear. +* ADC_FLAG_AWD: Analog watchdog flag. +* ADC_FLAG_EOC: End of conversion flag. +* ADC_FLAG_JEOC: End of injected group conversion flag. +* ADC_FLAG_JSTRT: Start of injected group conversion flag. +* ADC_FLAG_STRT: Start of regular group conversion flag. +* Return : None +*******************************************************************************/ +void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG) +{ + ADCx->STATR = ~(uint32_t)ADC_FLAG; +} + +/******************************************************************************* +* Function Name : ADC_GetITStatus +* Description : Checks whether the specified ADC interrupt has occurred or not. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_IT: specifies the ADC interrupt source to check. +* ADC_IT_EOC: End of conversion interrupt mask. +* ADC_IT_AWD: Analog watchdog interrupt mask. +* ADC_IT_JEOC: End of injected conversion interrupt mask. +* Return : ITStatus: SET or RESET. +*******************************************************************************/ +ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT) +{ + ITStatus bitstatus = RESET; + uint32_t itmask = 0, enablestatus = 0; + + itmask = ADC_IT >> 8; + enablestatus = (ADCx->CTLR1 & (uint8_t)ADC_IT) ; + + if (((ADCx->STATR & itmask) != (uint32_t)RESET) && enablestatus) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ADC_ClearITPendingBit +* Description : Clears the ADCx's interrupt pending bits. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* ADC_IT: specifies the ADC interrupt pending bit to clear. +* ADC_IT_EOC: End of conversion interrupt mask. +* ADC_IT_AWD: Analog watchdog interrupt mask. +* ADC_IT_JEOC: End of injected conversion interrupt mask. +* Return : None +*******************************************************************************/ +void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT) +{ + uint8_t itmask = 0; + + itmask = (uint8_t)(ADC_IT >> 8); + ADCx->STATR = ~(uint32_t)itmask; +} + +/******************************************************************************* +* Function Name : TempSensor_Volt_To_Temper +* Description : Internal Temperature Sensor Voltage to temperature. +* Input : Value: Voltage Value(mv). +* Return : Temper: Temperature Value. +*******************************************************************************/ +s32 TempSensor_Volt_To_Temper(s32 Value) +{ + s32 Temper, Refer_Volt, Refer_Temper; + s32 k=43; + + Refer_Volt = (s32)((*(u32*)0x1FFFF898)&0x0000FFFF); + Refer_Temper = (s32)(((*(u32*)0x1FFFF898)>>16) & 0x0000FFFF); + + Temper = Refer_Temper + ((Value-Refer_Volt)*10+(k>>1))/k; + + return Temper; +} + +/******************************************************************************* +* Function Name : ADC_BufferCmd +* Description : Enables or disables the ADCx buffer. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ADC_BufferCmd(ADC_TypeDef* ADCx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ADCx->CTLR1 |= (1<<26); + } + else + { + ADCx->CTLR1 &= ~(1<<26); + } +} + +/******************************************************************************* +* Function Name : Get_CalibrationValue +* Description : Get ADCx Calibration Value. +* Input : ADCx: +* where x can be 1 to select the ADC peripheral. +* Return : CalibrationValue +*******************************************************************************/ +int16_t Get_CalibrationValue(ADC_TypeDef* ADCx) +{ + __IO uint8_t i,j; + uint16_t buf[10]; + __IO uint16_t t; + + for(i=0; i<10; i++){ + ADC_ResetCalibration(ADC1); + while(ADC_GetResetCalibrationStatus(ADC1)); + ADC_StartCalibration(ADC1); + while(ADC_GetCalibrationStatus(ADC1)); + buf[i] = ADCx->RDATAR; + } + + for(i=0; i<10; i++){ + for(j=0; j<10; j++){ + if(buf[j]>buf[j+1]){ + t=buf[j]; + buf[j]=buf[j+1]; + buf[j]= t; + } + } + } + + t=0; + for(i=0; i<6; i++){ + t += buf[i+2]; + } + + t = (t/6)+((t%6)/3); + + return (int16_t)((int16_t)t-2048); +} + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_bkp.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_bkp.c new file mode 100644 index 00000000..1104d4c4 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_bkp.c @@ -0,0 +1,221 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_bkp.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the BKP firmware functions. +*******************************************************************************/ +#include "ch32v30x_bkp.h" +#include "ch32v30x_rcc.h" + +/* BKP registers bit mask */ + +/* OCTLR register bit mask */ +#define OCTLR_CAL_MASK ((uint16_t)0xFF80) +#define OCTLR_MASK ((uint16_t)0xFC7F) + +/******************************************************************************* +* Function Name : BKP_DeInit +* Description : Deinitializes the BKP peripheral registers to their default +* reset values. +* Input : None +* Return : None +*******************************************************************************/ +void BKP_DeInit(void) +{ + RCC_BackupResetCmd(ENABLE); + RCC_BackupResetCmd(DISABLE); +} + +/******************************************************************************* +* Function Name : BKP_TamperPinLevelConfig +* Description : Configures the Tamper Pin active level. +* Input : BKP_TamperPinLevel: specifies the Tamper Pin active level. +* BKP_TamperPinLevel_High: Tamper pin active on high level. +* BKP_TamperPinLevel_Low: Tamper pin active on low level. +* Return : None +*******************************************************************************/ +void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel) +{ + if(BKP_TamperPinLevel) + { + BKP->TPCTLR |= (1<<1); + } + else + { + BKP->TPCTLR &= ~(1<<1); + } +} + +/******************************************************************************* +* Function Name : BKP_TamperPinCmd +* Description : Enables or disables the Tamper Pin activation. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void BKP_TamperPinCmd(FunctionalState NewState) +{ + if(NewState) + { + BKP->TPCTLR |= (1<<0); + } + else + { + BKP->TPCTLR &= ~(1<<0); + } +} + +/******************************************************************************* +* Function Name : BKP_ITConfig +* Description : Enables or disables the Tamper Pin Interrupt. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void BKP_ITConfig(FunctionalState NewState) +{ + if(NewState) + { + BKP->TPCSR |= (1<<2); + } + else + { + BKP->TPCSR &= ~(1<<2); + } +} + +/******************************************************************************* +* Function Name : BKP_RTCOutputConfig +* Description : Select the RTC output source to output on the Tamper pin. +* Input : BKP_RTCOutputSource: specifies the RTC output source. +* BKP_RTCOutputSource_None: no RTC output on the Tamper pin. +* BKP_RTCOutputSource_CalibClock: output the RTC clock with +* frequency divided by 64 on the Tamper pin. +* BKP_RTCOutputSource_Alarm: output the RTC Alarm pulse signal +* on the Tamper pin. +* BKP_RTCOutputSource_Second: output the RTC Second pulse +* signal on the Tamper pin. +* Return : None +*******************************************************************************/ +void BKP_RTCOutputConfig(uint16_t BKP_RTCOutputSource) +{ + uint16_t tmpreg = 0; + + tmpreg = BKP->OCTLR; + tmpreg &= OCTLR_MASK; + tmpreg |= BKP_RTCOutputSource; + BKP->OCTLR = tmpreg; +} + +/******************************************************************************* +* Function Name : BKP_SetRTCCalibrationValue +* Description : Sets RTC Clock Calibration value. +* Input : CalibrationValue: specifies the RTC Clock Calibration value. +* This parameter must be a number between 0 and 0x1F. +* Return : None +*******************************************************************************/ +void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue) +{ + uint16_t tmpreg = 0; + + tmpreg = BKP->OCTLR; + tmpreg &= OCTLR_CAL_MASK; + tmpreg |= CalibrationValue; + BKP->OCTLR = tmpreg; +} + +/******************************************************************************* +* Function Name : BKP_WriteBackupRegister +* Description : Writes user data to the specified Data Backup Register. +* Input : BKP_DR: specifies the Data Backup Register. +* Data: data to write. +* Return : None +*******************************************************************************/ +void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + tmp = (uint32_t)BKP_BASE; + tmp += BKP_DR; + *(__IO uint32_t *) tmp = Data; +} + +/******************************************************************************* +* Function Name : BKP_ReadBackupRegister +* Description : Reads data from the specified Data Backup Register. +* Input : BKP_DR: specifies the Data Backup Register. +* This parameter can be BKP_DRx where x:[1, 42]. +* Return : None +*******************************************************************************/ +uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR) +{ + __IO uint32_t tmp = 0; + + tmp = (uint32_t)BKP_BASE; + tmp += BKP_DR; + + return (*(__IO uint16_t *) tmp); +} + +/******************************************************************************* +* Function Name : BKP_GetFlagStatus +* Description : Checks whether the Tamper Pin Event flag is set or not. +* Input : None +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus BKP_GetFlagStatus(void) +{ + if(BKP->TPCSR & (1<<8)) + { + return SET; + } + else + { + return RESET; + } +} + +/******************************************************************************* +* Function Name : BKP_ClearFlag +* Description : Clears Tamper Pin Event pending flag. +* Input : None +* Return : None +*******************************************************************************/ +void BKP_ClearFlag(void) +{ + BKP->TPCSR |= BKP_CTE; +} + +/******************************************************************************* +* Function Name : BKP_GetITStatus +* Description : Checks whether the Tamper Pin Interrupt has occurred or not. +* Input : None +* Return : ITStatus: SET or RESET. +*******************************************************************************/ +ITStatus BKP_GetITStatus(void) +{ + if(BKP->TPCSR & (1<<9)) + { + return SET; + } + else + { + return RESET; + } +} + +/******************************************************************************* +* Function Name : BKP_ClearITPendingBit +* Description : Clears Tamper Pin Interrupt pending bit. +* Input : None +* Return : None +*******************************************************************************/ +void BKP_ClearITPendingBit(void) +{ + BKP->TPCSR |= BKP_CTI; +} + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_can.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_can.c new file mode 100644 index 00000000..654f9ee1 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_can.c @@ -0,0 +1,1138 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_can.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the CAN firmware functions. +*******************************************************************************/ +#include "ch32v30x_can.h" +#include "ch32v30x_rcc.h" + +/* CAN CTLR Register bits */ +#define CTLR_DBF ((uint32_t)0x00010000) + +/* CAN Mailbox Transmit Request */ +#define TMIDxR_TXRQ ((uint32_t)0x00000001) + +/* CAN FCTLR Register bits */ +#define FCTLR_FINIT ((uint32_t)0x00000001) + +/* Time out for INAK bit */ +#define INAK_TIMEOUT ((uint32_t)0x0000FFFF) +/* Time out for SLAK bit */ +#define SLAK_TIMEOUT ((uint32_t)0x0000FFFF) + + +/* Flags in TSTATR register */ +#define CAN_FLAGS_TSTATR ((uint32_t)0x08000000) +/* Flags in RFIFO1 register */ +#define CAN_FLAGS_RFIFO1 ((uint32_t)0x04000000) +/* Flags in RFIFO0 register */ +#define CAN_FLAGS_RFIFO0 ((uint32_t)0x02000000) +/* Flags in STATR register */ +#define CAN_FLAGS_STATR ((uint32_t)0x01000000) +/* Flags in ERRSR register */ +#define CAN_FLAGS_ERRSR ((uint32_t)0x00F00000) + +/* Mailboxes definition */ +#define CAN_TXMAILBOX_0 ((uint8_t)0x00) +#define CAN_TXMAILBOX_1 ((uint8_t)0x01) +#define CAN_TXMAILBOX_2 ((uint8_t)0x02) + + +#define CAN_MODE_MASK ((uint32_t) 0x00000003) + +static ITStatus CheckITStatus(uint32_t CAN_Reg, uint32_t It_Bit); + + +/******************************************************************************* +* Function Name : CAN_DeInit +* Description : Deinitializes the CAN peripheral registers to their default +* reset values. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* Return : None +*******************************************************************************/ +void CAN_DeInit(CAN_TypeDef* CANx) +{ + if (CANx == CAN1) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, DISABLE); + } + else + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN2, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN2, DISABLE); + } +} + +/******************************************************************************* +* Function Name : CAN_Init +* Description : Initializes the CAN peripheral according to the specified +* parameters in the CAN_InitStruct. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* CAN_InitStruct: pointer to a CAN_InitTypeDef structure that +* contains the configuration information for the CAN peripheral. +* Return : InitStatus: +* CAN_InitStatus_Failed. +* CAN_InitStatus_Success. +*******************************************************************************/ +uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct) +{ + uint8_t InitStatus = CAN_InitStatus_Failed; + uint32_t wait_ack = 0x00000000; + + CANx->CTLR &= (~(uint32_t)CAN_CTLR_SLEEP); + CANx->CTLR |= CAN_CTLR_INRQ ; + + while (((CANx->STATR & CAN_STATR_INAK) != CAN_STATR_INAK) && (wait_ack != INAK_TIMEOUT)) + { + wait_ack++; + } + + if ((CANx->STATR & CAN_STATR_INAK) != CAN_STATR_INAK) + { + InitStatus = CAN_InitStatus_Failed; + } + else + { + if (CAN_InitStruct->CAN_TTCM == ENABLE) + { + CANx->CTLR |= CAN_CTLR_TTCM; + } + else + { + CANx->CTLR &= ~(uint32_t)CAN_CTLR_TTCM; + } + + if (CAN_InitStruct->CAN_ABOM == ENABLE) + { + CANx->CTLR |= CAN_CTLR_ABOM; + } + else + { + CANx->CTLR &= ~(uint32_t)CAN_CTLR_ABOM; + } + + if (CAN_InitStruct->CAN_AWUM == ENABLE) + { + CANx->CTLR |= CAN_CTLR_AWUM; + } + else + { + CANx->CTLR &= ~(uint32_t)CAN_CTLR_AWUM; + } + + if (CAN_InitStruct->CAN_NART == ENABLE) + { + CANx->CTLR |= CAN_CTLR_NART; + } + else + { + CANx->CTLR &= ~(uint32_t)CAN_CTLR_NART; + } + + if (CAN_InitStruct->CAN_RFLM == ENABLE) + { + CANx->CTLR |= CAN_CTLR_RFLM; + } + else + { + CANx->CTLR &= ~(uint32_t)CAN_CTLR_RFLM; + } + + if (CAN_InitStruct->CAN_TXFP == ENABLE) + { + CANx->CTLR |= CAN_CTLR_TXFP; + } + else + { + CANx->CTLR &= ~(uint32_t)CAN_CTLR_TXFP; + } + + CANx->BTIMR = (uint32_t)((uint32_t)CAN_InitStruct->CAN_Mode << 30) | \ + ((uint32_t)CAN_InitStruct->CAN_SJW << 24) | \ + ((uint32_t)CAN_InitStruct->CAN_BS1 << 16) | \ + ((uint32_t)CAN_InitStruct->CAN_BS2 << 20) | \ + ((uint32_t)CAN_InitStruct->CAN_Prescaler - 1); + CANx->CTLR &= ~(uint32_t)CAN_CTLR_INRQ; + wait_ack = 0; + + while (((CANx->STATR & CAN_STATR_INAK) == CAN_STATR_INAK) && (wait_ack != INAK_TIMEOUT)) + { + wait_ack++; + } + + if ((CANx->STATR & CAN_STATR_INAK) == CAN_STATR_INAK) + { + InitStatus = CAN_InitStatus_Failed; + } + else + { + InitStatus = CAN_InitStatus_Success ; + } + } + + return InitStatus; +} + +/******************************************************************************* +* Function Name : CAN_FilterInit +* Description : Initializes the CAN peripheral according to the specified +* parameters in the CAN_FilterInitStruct. +* Input : CAN_FilterInitStruct: pointer to a CAN_FilterInitTypeDef +* structure that contains the configuration information. +* Return : None +*******************************************************************************/ +void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct) +{ + uint32_t filter_number_bit_pos = 0; + + filter_number_bit_pos = ((uint32_t)1) << CAN_FilterInitStruct->CAN_FilterNumber; + CAN1->FCTLR |= FCTLR_FINIT; + CAN1->FWR &= ~(uint32_t)filter_number_bit_pos; + + if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_16bit) + { + CAN1->FSCFGR &= ~(uint32_t)filter_number_bit_pos; + + CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 = + ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow) << 16) | + (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow); + + CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 = + ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) | + (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh); + } + + if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_32bit) + { + CAN1->FSCFGR |= filter_number_bit_pos; + + CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 = + ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh) << 16) | + (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow); + + CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 = + ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) | + (0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow); + } + + if (CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdMask) + { + CAN1->FMCFGR &= ~(uint32_t)filter_number_bit_pos; + } + else + { + CAN1->FMCFGR |= (uint32_t)filter_number_bit_pos; + } + + if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_Filter_FIFO0) + { + CAN1->FAFIFOR &= ~(uint32_t)filter_number_bit_pos; + } + + if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_Filter_FIFO1) + { + CAN1->FAFIFOR |= (uint32_t)filter_number_bit_pos; + } + + if (CAN_FilterInitStruct->CAN_FilterActivation == ENABLE) + { + CAN1->FWR |= filter_number_bit_pos; + } + + CAN1->FCTLR &= ~FCTLR_FINIT; +} + +/******************************************************************************* +* Function Name : CAN_StructInit +* Description : Fills each CAN_InitStruct member with its default value. +* Input : CAN_InitStruct: pointer to a CAN_InitTypeDef structure which +* will be initialized. +* Return : None +*******************************************************************************/ +void CAN_StructInit(CAN_InitTypeDef* CAN_InitStruct) +{ + CAN_InitStruct->CAN_TTCM = DISABLE; + CAN_InitStruct->CAN_ABOM = DISABLE; + CAN_InitStruct->CAN_AWUM = DISABLE; + CAN_InitStruct->CAN_NART = DISABLE; + CAN_InitStruct->CAN_RFLM = DISABLE; + CAN_InitStruct->CAN_TXFP = DISABLE; + CAN_InitStruct->CAN_Mode = CAN_Mode_Normal; + CAN_InitStruct->CAN_SJW = CAN_SJW_1tq; + CAN_InitStruct->CAN_BS1 = CAN_BS1_4tq; + CAN_InitStruct->CAN_BS2 = CAN_BS2_3tq; + CAN_InitStruct->CAN_Prescaler = 1; +} + +/******************************************************************************* +* Function Name : CAN_SlaveStartBank +* Description : This function applies only to CH32 Connectivity line devices. +* Input : CAN_BankNumber: Select the start slave bank filter from 1..27. +* Return : None +*******************************************************************************/ +void CAN_SlaveStartBank(uint8_t CAN_BankNumber) +{ + CAN1->FCTLR |= FCTLR_FINIT; + CAN1->FCTLR &= (uint32_t)0xFFFFC0F1 ; + CAN1->FCTLR |= (uint32_t)(CAN_BankNumber)<<8; + CAN1->FCTLR &= ~FCTLR_FINIT; +} + +/******************************************************************************* +* Function Name : CAN_DBGFreeze +* Description : Enables or disables the DBG Freeze for CAN. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void CAN_DBGFreeze(CAN_TypeDef* CANx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + CANx->CTLR |= CTLR_DBF; + } + else + { + CANx->CTLR &= ~CTLR_DBF; + } +} + +/******************************************************************************* +* Function Name : CAN_TTComModeCmd +* Description : Enables or disabes the CAN Time TriggerOperation communication mode. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void CAN_TTComModeCmd(CAN_TypeDef* CANx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + CANx->CTLR |= CAN_CTLR_TTCM; + + CANx->sTxMailBox[0].TXMDTR |= ((uint32_t)CAN_TXMDT0R_TGT); + CANx->sTxMailBox[1].TXMDTR |= ((uint32_t)CAN_TXMDT1R_TGT); + CANx->sTxMailBox[2].TXMDTR |= ((uint32_t)CAN_TXMDT2R_TGT); + } + else + { + CANx->CTLR &= (uint32_t)(~(uint32_t)CAN_CTLR_TTCM); + + CANx->sTxMailBox[0].TXMDTR &= ((uint32_t)~CAN_TXMDT0R_TGT); + CANx->sTxMailBox[1].TXMDTR &= ((uint32_t)~CAN_TXMDT1R_TGT); + CANx->sTxMailBox[2].TXMDTR &= ((uint32_t)~CAN_TXMDT2R_TGT); + } +} + +/******************************************************************************* +* Function Name : CAN_Transmit +* Description : Initiates the transmission of a message. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* TxMessage: pointer to a structure which contains CAN Id, CAN +* DLC and CAN data. +* Return : transmit_mailbox: The number of the mailbox that is used for +* transmission or CAN_TxStatus_NoMailBox if there is no empty mailbox. +*******************************************************************************/ +uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage) +{ + uint8_t transmit_mailbox = 0; + + if ((CANx->TSTATR&CAN_TSTATR_TME0) == CAN_TSTATR_TME0) + { + transmit_mailbox = 0; + } + else if ((CANx->TSTATR&CAN_TSTATR_TME1) == CAN_TSTATR_TME1) + { + transmit_mailbox = 1; + } + else if ((CANx->TSTATR&CAN_TSTATR_TME2) == CAN_TSTATR_TME2) + { + transmit_mailbox = 2; + } + else + { + transmit_mailbox = CAN_TxStatus_NoMailBox; + } + + if (transmit_mailbox != CAN_TxStatus_NoMailBox) + { + CANx->sTxMailBox[transmit_mailbox].TXMIR &= TMIDxR_TXRQ; + if (TxMessage->IDE == CAN_Id_Standard) + { + CANx->sTxMailBox[transmit_mailbox].TXMIR |= ((TxMessage->StdId << 21) | \ + TxMessage->RTR); + } + else + { + CANx->sTxMailBox[transmit_mailbox].TXMIR |= ((TxMessage->ExtId << 3) | \ + TxMessage->IDE | \ + TxMessage->RTR); + } + + TxMessage->DLC &= (uint8_t)0x0000000F; + CANx->sTxMailBox[transmit_mailbox].TXMDTR &= (uint32_t)0xFFFFFFF0; + CANx->sTxMailBox[transmit_mailbox].TXMDTR |= TxMessage->DLC; + + CANx->sTxMailBox[transmit_mailbox].TXMDLR = (((uint32_t)TxMessage->Data[3] << 24) | + ((uint32_t)TxMessage->Data[2] << 16) | + ((uint32_t)TxMessage->Data[1] << 8) | + ((uint32_t)TxMessage->Data[0])); + CANx->sTxMailBox[transmit_mailbox].TXMDHR = (((uint32_t)TxMessage->Data[7] << 24) | + ((uint32_t)TxMessage->Data[6] << 16) | + ((uint32_t)TxMessage->Data[5] << 8) | + ((uint32_t)TxMessage->Data[4])); + CANx->sTxMailBox[transmit_mailbox].TXMIR |= TMIDxR_TXRQ; + } + + return transmit_mailbox; +} + +/******************************************************************************* +* Function Name : CAN_TransmitStatus +* Description : Checks the transmission of a message. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* TransmitMailbox: the number of the mailbox that is used for +* transmission. +* Return : state: +* CAN_TxStatus_Ok. +* CAN_TxStatus_Failed. +*******************************************************************************/ +uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox) +{ + uint32_t state = 0; + + switch (TransmitMailbox) + { + case (CAN_TXMAILBOX_0): + state = CANx->TSTATR & (CAN_TSTATR_RQCP0 | CAN_TSTATR_TXOK0 | CAN_TSTATR_TME0); + break; + + case (CAN_TXMAILBOX_1): + state = CANx->TSTATR & (CAN_TSTATR_RQCP1 | CAN_TSTATR_TXOK1 | CAN_TSTATR_TME1); + break; + + case (CAN_TXMAILBOX_2): + state = CANx->TSTATR & (CAN_TSTATR_RQCP2 | CAN_TSTATR_TXOK2 | CAN_TSTATR_TME2); + break; + + default: + state = CAN_TxStatus_Failed; + break; + } + + switch (state) + { + case (0x0): + state = CAN_TxStatus_Pending; + break; + + case (CAN_TSTATR_RQCP0 | CAN_TSTATR_TME0): + state = CAN_TxStatus_Failed; + break; + + case (CAN_TSTATR_RQCP1 | CAN_TSTATR_TME1): + state = CAN_TxStatus_Failed; + break; + + case (CAN_TSTATR_RQCP2 | CAN_TSTATR_TME2): + state = CAN_TxStatus_Failed; + break; + + case (CAN_TSTATR_RQCP0 | CAN_TSTATR_TXOK0 | CAN_TSTATR_TME0): + state = CAN_TxStatus_Ok; + break; + + case (CAN_TSTATR_RQCP1 | CAN_TSTATR_TXOK1 | CAN_TSTATR_TME1): + state = CAN_TxStatus_Ok; + break; + + case (CAN_TSTATR_RQCP2 | CAN_TSTATR_TXOK2 | CAN_TSTATR_TME2): + state = CAN_TxStatus_Ok; + break; + + default: + state = CAN_TxStatus_Failed; + break; + } + + return (uint8_t) state; +} + +/******************************************************************************* +* Function Name : CAN_CancelTransmit +* Description : Cancels a transmit request. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* Mailbox: Mailbox number. +* CAN_TXMAILBOX_0. +* CAN_TXMAILBOX_1. +* CAN_TXMAILBOX_2. +* Return : None +*******************************************************************************/ +void CAN_CancelTransmit(CAN_TypeDef* CANx, uint8_t Mailbox) +{ + switch (Mailbox) + { + case (CAN_TXMAILBOX_0): + CANx->TSTATR |= CAN_TSTATR_ABRQ0; + break; + + case (CAN_TXMAILBOX_1): + CANx->TSTATR |= CAN_TSTATR_ABRQ1; + break; + + case (CAN_TXMAILBOX_2): + CANx->TSTATR |= CAN_TSTATR_ABRQ2; + break; + + default: + break; + } +} + +/******************************************************************************* +* Function Name : CAN_Receive +* Description : Receives a message. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* FIFONumber: Receive FIFO number. +* CAN_FIFO0. +* CAN_FIFO1. +* RxMessage: pointer to a structure receive message which contains +* CAN Id, CAN DLC, CAN datas and FMI number. +* Return : None +*******************************************************************************/ +void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage) +{ + RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONumber].RXMIR; + + if (RxMessage->IDE == CAN_Id_Standard) + { + RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONumber].RXMIR >> 21); + } + else + { + RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONumber].RXMIR >> 3); + } + + RxMessage->RTR = (uint8_t)0x02 & CANx->sFIFOMailBox[FIFONumber].RXMIR; + RxMessage->DLC = (uint8_t)0x0F & CANx->sFIFOMailBox[FIFONumber].RXMDTR; + RxMessage->FMI = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RXMDTR >> 8); + RxMessage->Data[0] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RXMDLR; + RxMessage->Data[1] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RXMDLR >> 8); + RxMessage->Data[2] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RXMDLR >> 16); + RxMessage->Data[3] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RXMDLR >> 24); + RxMessage->Data[4] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RXMDHR; + RxMessage->Data[5] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RXMDHR >> 8); + RxMessage->Data[6] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RXMDHR >> 16); + RxMessage->Data[7] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RXMDHR >> 24); + + if (FIFONumber == CAN_FIFO0) + { + CANx->RFIFO0 |= CAN_RFIFO0_RFOM0; + } + else + { + CANx->RFIFO1 |= CAN_RFIFO1_RFOM1; + } +} + +/******************************************************************************* +* Function Name : CAN_FIFORelease +* Description : Releases the specified FIFO. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* FIFONumber: FIFO to release. +* CAN_FIFO0. +* CAN_FIFO1. +* Return : None +*******************************************************************************/ +void CAN_FIFORelease(CAN_TypeDef* CANx, uint8_t FIFONumber) +{ + if (FIFONumber == CAN_FIFO0) + { + CANx->RFIFO0 |= CAN_RFIFO0_RFOM0; + } + else + { + CANx->RFIFO1 |= CAN_RFIFO1_RFOM1; + } +} + +/******************************************************************************* +* Function Name : CAN_MessagePending +* Description : Returns the number of pending messages. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* FIFONumber: Receive FIFO number. +* CAN_FIFO0. +* CAN_FIFO1. +* Return : message_pending: which is the number of pending message. +*******************************************************************************/ +uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber) +{ + uint8_t message_pending=0; + + if (FIFONumber == CAN_FIFO0) + { + message_pending = (uint8_t)(CANx->RFIFO0&(uint32_t)0x03); + } + else if (FIFONumber == CAN_FIFO1) + { + message_pending = (uint8_t)(CANx->RFIFO1&(uint32_t)0x03); + } + else + { + message_pending = 0; + } + + return message_pending; +} + +/******************************************************************************* +* Function Name : CAN_OperatingModeRequest +* Description : Select the CAN Operation mode. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* CAN_OperatingMode : CAN Operating Mode. +* CAN_OperatingMode_Initialization. +* CAN_OperatingMode_Normal. +* CAN_OperatingMode_Sleep. +* Return : status: +* CAN_ModeStatus_Failed: CAN failed entering the specific mode. +* CAN_ModeStatus_Success: CAN Succeed entering the specific mode. +*******************************************************************************/ +uint8_t CAN_OperatingModeRequest(CAN_TypeDef* CANx, uint8_t CAN_OperatingMode) +{ + uint8_t status = CAN_ModeStatus_Failed; + uint32_t timeout = INAK_TIMEOUT; + + if (CAN_OperatingMode == CAN_OperatingMode_Initialization) + { + CANx->CTLR = (uint32_t)((CANx->CTLR & (uint32_t)(~(uint32_t)CAN_CTLR_SLEEP)) | CAN_CTLR_INRQ); + + while (((CANx->STATR & CAN_MODE_MASK) != CAN_STATR_INAK) && (timeout != 0)) + { + timeout--; + } + if ((CANx->STATR & CAN_MODE_MASK) != CAN_STATR_INAK) + { + status = CAN_ModeStatus_Failed; + } + else + { + status = CAN_ModeStatus_Success; + } + } + else if (CAN_OperatingMode == CAN_OperatingMode_Normal) + { + CANx->CTLR &= (uint32_t)(~(CAN_CTLR_SLEEP|CAN_CTLR_INRQ)); + + while (((CANx->STATR & CAN_MODE_MASK) != 0) && (timeout!=0)) + { + timeout--; + } + if ((CANx->STATR & CAN_MODE_MASK) != 0) + { + status = CAN_ModeStatus_Failed; + } + else + { + status = CAN_ModeStatus_Success; + } + } + else if (CAN_OperatingMode == CAN_OperatingMode_Sleep) + { + CANx->CTLR = (uint32_t)((CANx->CTLR & (uint32_t)(~(uint32_t)CAN_CTLR_INRQ)) | CAN_CTLR_SLEEP); + + while (((CANx->STATR & CAN_MODE_MASK) != CAN_STATR_SLAK) && (timeout!=0)) + { + timeout--; + } + if ((CANx->STATR & CAN_MODE_MASK) != CAN_STATR_SLAK) + { + status = CAN_ModeStatus_Failed; + } + else + { + status = CAN_ModeStatus_Success; + } + } + else + { + status = CAN_ModeStatus_Failed; + } + + return (uint8_t) status; +} + +/******************************************************************************* +* Function Name : CAN_Sleep +* Description : Enters the low power mode. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* Return : sleepstatus: +* CAN_Sleep_Ok. +* CAN_Sleep_Failed. +*******************************************************************************/ +uint8_t CAN_Sleep(CAN_TypeDef* CANx) +{ + uint8_t sleepstatus = CAN_Sleep_Failed; + + CANx->CTLR = (((CANx->CTLR) & (uint32_t)(~(uint32_t)CAN_CTLR_INRQ)) | CAN_CTLR_SLEEP); + + if ((CANx->STATR & (CAN_STATR_SLAK|CAN_STATR_INAK)) == CAN_STATR_SLAK) + { + sleepstatus = CAN_Sleep_Ok; + } + + return (uint8_t)sleepstatus; +} + +/******************************************************************************* +* Function Name : CAN_WakeUp +* Description : Wakes the CAN up. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* Return : wakeupstatus: +* CAN_WakeUp_Ok. +* CAN_WakeUp_Failed. +*******************************************************************************/ +uint8_t CAN_WakeUp(CAN_TypeDef* CANx) +{ + uint32_t wait_slak = SLAK_TIMEOUT; + uint8_t wakeupstatus = CAN_WakeUp_Failed; + + CANx->CTLR &= ~(uint32_t)CAN_CTLR_SLEEP; + + while(((CANx->STATR & CAN_STATR_SLAK) == CAN_STATR_SLAK)&&(wait_slak!=0x00)) + { + wait_slak--; + } + if((CANx->STATR & CAN_STATR_SLAK) != CAN_STATR_SLAK) + { + wakeupstatus = CAN_WakeUp_Ok; + } + + return (uint8_t)wakeupstatus; +} + +/******************************************************************************* +* Function Name : CAN_GetLastErrorCode +* Description : Returns the CANx's last error code (LEC). +* Input : CANx: where x can be 1 to select the CAN peripheral. +* Return : errorcode: specifies the Error code. +* CAN_ErrorCode_NoErr: No Error. +* CAN_ErrorCode_StuffErr: Stuff Error. +* CAN_ErrorCode_FormErr: Form Error. +* CAN_ErrorCode_ACKErr: Acknowledgment Error. +* CAN_ErrorCode_BitRecessiveErr: Bit Recessive Error. +* CAN_ErrorCode_BitDominantErr: Bit Dominant Error. +* CAN_ErrorCode_CRCErr: CRC Error. +* CAN_ErrorCode_SoftwareSetErr: Software Set Error. +*******************************************************************************/ +uint8_t CAN_GetLastErrorCode(CAN_TypeDef* CANx) +{ + uint8_t errorcode=0; + + errorcode = (((uint8_t)CANx->ERRSR) & (uint8_t)CAN_ERRSR_LEC); + + return errorcode; +} + +/******************************************************************************* +* Function Name : CAN_GetReceiveErrorCounter +* Description : Returns the CANx Receive Error Counter (REC). +* Input : CANx: where x can be 1 to select the CAN peripheral. +* Return : counter: CAN Receive Error Counter. +*******************************************************************************/ +uint8_t CAN_GetReceiveErrorCounter(CAN_TypeDef* CANx) +{ + uint8_t counter=0; + + counter = (uint8_t)((CANx->ERRSR & CAN_ERRSR_REC)>> 24); + + return counter; +} + +/******************************************************************************* +* Function Name : CAN_GetLSBTransmitErrorCounter +* Description : Returns the LSB of the 9-bit CANx Transmit Error Counter(TEC). +* Input : CANx: where x can be 1 to select the CAN peripheral. +* Return : counter: LSB of the 9-bit CAN Transmit Error Counter. +*******************************************************************************/ +uint8_t CAN_GetLSBTransmitErrorCounter(CAN_TypeDef* CANx) +{ + uint8_t counter=0; + + counter = (uint8_t)((CANx->ERRSR & CAN_ERRSR_TEC)>> 16); + + return counter; +} + +/******************************************************************************* +* Function Name : CAN_ITConfig +* Description : Enables or disables the specified CANx interrupts. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* CAN_IT: specifies the CAN interrupt sources to be enabled or disabled. +* CAN_IT_TME. +* CAN_IT_FMP0. +* CAN_IT_FF0. +* CAN_IT_FOV0. +* CAN_IT_FMP1. +* CAN_IT_FF1. +* CAN_IT_FOV1. +* CAN_IT_EWG. +* CAN_IT_EPV. +* CAN_IT_LEC. +* CAN_IT_ERR. +* CAN_IT_WKU. +* CAN_IT_SLK. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void CAN_ITConfig(CAN_TypeDef* CANx, uint32_t CAN_IT, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + CANx->INTENR |= CAN_IT; + } + else + { + CANx->INTENR &= ~CAN_IT; + } +} + +/******************************************************************************* +* Function Name : CAN_GetFlagStatus +* Description : Checks whether the specified CAN flag is set or not. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* CAN_FLAG: specifies the flag to check. +* CAN_FLAG_EWG. +* CAN_FLAG_EPV. +* CAN_FLAG_BOF. +* CAN_FLAG_RQCP0. +* CAN_FLAG_RQCP1. +* CAN_FLAG_RQCP2. +* CAN_FLAG_FMP1. +* CAN_FLAG_FF1. +* CAN_FLAG_FOV1. +* CAN_FLAG_FMP0. +* CAN_FLAG_FF0. +* CAN_FLAG_FOV0. +* CAN_FLAG_WKU. +* CAN_FLAG_SLAK. +* CAN_FLAG_LEC. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus CAN_GetFlagStatus(CAN_TypeDef* CANx, uint32_t CAN_FLAG) +{ + FlagStatus bitstatus = RESET; + + if((CAN_FLAG & CAN_FLAGS_ERRSR) != (uint32_t)RESET) + { + if ((CANx->ERRSR & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else if((CAN_FLAG & CAN_FLAGS_STATR) != (uint32_t)RESET) + { + if ((CANx->STATR & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else if((CAN_FLAG & CAN_FLAGS_TSTATR) != (uint32_t)RESET) + { + if ((CANx->TSTATR & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else if((CAN_FLAG & CAN_FLAGS_RFIFO0) != (uint32_t)RESET) + { + if ((CANx->RFIFO0 & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else + { + if ((uint32_t)(CANx->RFIFO1 & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : CAN_ClearFlag +* Description : Clears the CAN's pending flags. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* CAN_FLAG: specifies the flag to clear. +* CAN_FLAG_RQCP0. +* CAN_FLAG_RQCP1. +* CAN_FLAG_RQCP2. +* CAN_FLAG_FF1. +* CAN_FLAG_FOV1. +* CAN_FLAG_FF0. +* CAN_FLAG_FOV0. +* CAN_FLAG_WKU. +* CAN_FLAG_SLAK. +* CAN_FLAG_LEC. +* Return : None +*******************************************************************************/ +void CAN_ClearFlag(CAN_TypeDef* CANx, uint32_t CAN_FLAG) +{ + uint32_t flagtmp=0; + + if (CAN_FLAG == CAN_FLAG_LEC) + { + CANx->ERRSR = (uint32_t)RESET; + } + else + { + flagtmp = CAN_FLAG & 0x000FFFFF; + + if ((CAN_FLAG & CAN_FLAGS_RFIFO0)!=(uint32_t)RESET) + { + CANx->RFIFO0 = (uint32_t)(flagtmp); + } + else if ((CAN_FLAG & CAN_FLAGS_RFIFO1)!=(uint32_t)RESET) + { + CANx->RFIFO1 = (uint32_t)(flagtmp); + } + else if ((CAN_FLAG & CAN_FLAGS_TSTATR)!=(uint32_t)RESET) + { + CANx->TSTATR = (uint32_t)(flagtmp); + } + else + { + CANx->STATR = (uint32_t)(flagtmp); + } + } +} + +/******************************************************************************* +* Function Name : CAN_GetITStatus +* Description : Checks whether the specified CANx interrupt has occurred or not. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* CAN_IT: specifies the CAN interrupt source to check. +* CAN_IT_TME. +* CAN_IT_FMP0. +* CAN_IT_FF0. +* CAN_IT_FOV0. +* CAN_IT_FMP1. +* CAN_IT_FF1. +* CAN_IT_FOV1. +* CAN_IT_WKU. +* CAN_IT_SLK. +* CAN_IT_EWG. +* CAN_IT_EPV. +* CAN_IT_BOF. +* CAN_IT_LEC. +* CAN_IT_ERR. +* Return : ITStatus: SET or RESET. +*******************************************************************************/ +ITStatus CAN_GetITStatus(CAN_TypeDef* CANx, uint32_t CAN_IT) +{ + ITStatus itstatus = RESET; + + if((CANx->INTENR & CAN_IT) != RESET) + { + switch (CAN_IT) + { + case CAN_IT_TME: + itstatus = CheckITStatus(CANx->TSTATR, CAN_TSTATR_RQCP0|CAN_TSTATR_RQCP1|CAN_TSTATR_RQCP2); + break; + + case CAN_IT_FMP0: + itstatus = CheckITStatus(CANx->RFIFO0, CAN_RFIFO0_FMP0); + break; + + case CAN_IT_FF0: + itstatus = CheckITStatus(CANx->RFIFO0, CAN_RFIFO0_FULL0); + break; + + case CAN_IT_FOV0: + itstatus = CheckITStatus(CANx->RFIFO0, CAN_RFIFO0_FOVR0); + break; + + case CAN_IT_FMP1: + itstatus = CheckITStatus(CANx->RFIFO1, CAN_RFIFO1_FMP1); + break; + + case CAN_IT_FF1: + itstatus = CheckITStatus(CANx->RFIFO1, CAN_RFIFO1_FULL1); + break; + + case CAN_IT_FOV1: + itstatus = CheckITStatus(CANx->RFIFO1, CAN_RFIFO1_FOVR1); + break; + + case CAN_IT_WKU: + itstatus = CheckITStatus(CANx->STATR, CAN_STATR_WKUI); + break; + + case CAN_IT_SLK: + itstatus = CheckITStatus(CANx->STATR, CAN_STATR_SLAKI); + break; + + case CAN_IT_EWG: + itstatus = CheckITStatus(CANx->ERRSR, CAN_ERRSR_EWGF); + break; + + case CAN_IT_EPV: + itstatus = CheckITStatus(CANx->ERRSR, CAN_ERRSR_EPVF); + break; + + case CAN_IT_BOF: + itstatus = CheckITStatus(CANx->ERRSR, CAN_ERRSR_BOFF); + break; + + case CAN_IT_LEC: + itstatus = CheckITStatus(CANx->ERRSR, CAN_ERRSR_LEC); + break; + + case CAN_IT_ERR: + itstatus = CheckITStatus(CANx->STATR, CAN_STATR_ERRI); + break; + + default : + itstatus = RESET; + break; + } + } + else + { + itstatus = RESET; + } + + return itstatus; +} + +/******************************************************************************* +* Function Name : CAN_ClearITPendingBit +* Description : Clears the CANx's interrupt pending bits. +* Input : CANx: where x can be 1 to select the CAN peripheral. +* CAN_IT: specifies the interrupt pending bit to clear. +* CAN_IT_TME. +* CAN_IT_FF0. +* CAN_IT_FOV0. +* CAN_IT_FF1. +* CAN_IT_FOV1. +* CAN_IT_WKU. +* CAN_IT_SLK. +* CAN_IT_EWG. +* CAN_IT_EPV. +* CAN_IT_BOF. +* CAN_IT_LEC. +* CAN_IT_ERR. +* Return : None +*******************************************************************************/ +void CAN_ClearITPendingBit(CAN_TypeDef* CANx, uint32_t CAN_IT) +{ + switch (CAN_IT) + { + case CAN_IT_TME: + CANx->TSTATR = CAN_TSTATR_RQCP0|CAN_TSTATR_RQCP1|CAN_TSTATR_RQCP2; + break; + + case CAN_IT_FF0: + CANx->RFIFO0 = CAN_RFIFO0_FULL0; + break; + + case CAN_IT_FOV0: + CANx->RFIFO0 = CAN_RFIFO0_FOVR0; + break; + + case CAN_IT_FF1: + CANx->RFIFO1 = CAN_RFIFO1_FULL1; + break; + + case CAN_IT_FOV1: + CANx->RFIFO1 = CAN_RFIFO1_FOVR1; + break; + + case CAN_IT_WKU: + CANx->STATR = CAN_STATR_WKUI; + break; + + case CAN_IT_SLK: + CANx->STATR = CAN_STATR_SLAKI; + break; + + case CAN_IT_EWG: + CANx->STATR = CAN_STATR_ERRI; + break; + + case CAN_IT_EPV: + CANx->STATR = CAN_STATR_ERRI; + break; + + case CAN_IT_BOF: + CANx->STATR = CAN_STATR_ERRI; + break; + + case CAN_IT_LEC: + CANx->ERRSR = RESET; + CANx->STATR = CAN_STATR_ERRI; + break; + + case CAN_IT_ERR: + CANx->ERRSR = RESET; + CANx->STATR = CAN_STATR_ERRI; + break; + + default : + break; + } +} + +/******************************************************************************* +* Function Name : CheckITStatus +* Description : Checks whether the CAN interrupt has occurred or not. +* Input : CAN_Reg: specifies the CAN interrupt register to check +* It_Bit: specifies the interrupt source bit to check. +* Return : ITStatus: SET or RESET. +*******************************************************************************/ +static ITStatus CheckITStatus(uint32_t CAN_Reg, uint32_t It_Bit) +{ + ITStatus pendingbitstatus = RESET; + + if ((CAN_Reg & It_Bit) != (uint32_t)RESET) + { + pendingbitstatus = SET; + } + else + { + pendingbitstatus = RESET; + } + + return pendingbitstatus; +} + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_crc.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_crc.c new file mode 100644 index 00000000..ab01e3f6 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_crc.c @@ -0,0 +1,92 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_crc.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the CRC firmware functions. +*******************************************************************************/ +#include "ch32v30x_crc.h" + +/******************************************************************************* +* Function Name : CRC_ResetDR +* Description : Resets the CRC Data register (DR). +* Input : None +* Return : None +*******************************************************************************/ +void CRC_ResetDR(void) +{ + CRC->CTLR = CRC_CTLR_RESET; +} + +/******************************************************************************* +* Function Name : CRC_CalcCRC +* Description : Computes the 32-bit CRC of a given data word(32-bit). +* Input : Data: data word(32-bit) to compute its CRC. +* Return : 32-bit CRC. +*******************************************************************************/ +uint32_t CRC_CalcCRC(uint32_t Data) +{ + CRC->DATAR = Data; + + return (CRC->DATAR); +} + +/******************************************************************************* +* Function Name : CRC_CalcBlockCRC +* Description : Computes the 32-bit CRC of a given buffer of data word(32-bit). +* Input : pBuffer: pointer to the buffer containing the data to be computed. +* BufferLength: length of the buffer to be computed. +* Return : 32-bit CRC. +*******************************************************************************/ +uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength) +{ + uint32_t index = 0; + + for(index = 0; index < BufferLength; index++) + { + CRC->DATAR = pBuffer[index]; + } + + return (CRC->DATAR); +} + +/******************************************************************************* +* Function Name : CRC_GetCRC +* Description : Returns the current CRC value. +* Input : None +* Return : 32-bit CRC. +*******************************************************************************/ +uint32_t CRC_GetCRC(void) +{ + return (CRC->IDATAR); +} + +/******************************************************************************* +* Function Name : CRC_SetIDRegister +* Description : Stores a 8-bit data in the Independent Data(ID) register. +* Input : IDValue: 8-bit value to be stored in the ID register. +* Return : None +*******************************************************************************/ +void CRC_SetIDRegister(uint8_t IDValue) +{ + CRC->IDATAR = IDValue; +} + +/******************************************************************************* +* Function Name : CRC_GetIDRegister +* Description : Returns the 8-bit data stored in the Independent Data(ID) register. +* Input : None +* Return : 8-bit value of the ID register. +*******************************************************************************/ +uint8_t CRC_GetIDRegister(void) +{ + return (CRC->IDATAR); +} + + + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dac.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dac.c new file mode 100644 index 00000000..ba60f41a --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dac.c @@ -0,0 +1,269 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_dac.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the DAC firmware functions. +****************************************************************************************/ +#include "ch32v30x_dac.h" +#include "ch32v30x_rcc.h" + +/* CTLR register Mask */ +#define CTLR_CLEAR_MASK ((uint32_t)0x00000FFE) + +/* DAC Dual Channels SWTR masks */ +#define DUAL_SWTR_SET ((uint32_t)0x00000003) +#define DUAL_SWTR_RESET ((uint32_t)0xFFFFFFFC) + +/* DHR registers offsets */ +#define DHR12R1_OFFSET ((uint32_t)0x00000008) +#define DHR12R2_OFFSET ((uint32_t)0x00000014) +#define DHR12RD_OFFSET ((uint32_t)0x00000020) + +/* DOR register offset */ +#define DOR_OFFSET ((uint32_t)0x0000002C) + + +/****************************************************************************************** +* Function Name : DAC_DeInit +* Description : Deinitializes the DAC peripheral registers to their default reset values. +* Input : None +* Return : None +*******************************************************************************************/ +void DAC_DeInit(void) +{ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, DISABLE); +} + +/****************************************************************************************** +* Function Name : DAC_Init +* Description : Initializes the DAC peripheral according to the specified parameters in +* the DAC_InitStruct. +* Input : DAC_Channel:the selected DAC channel. +* DAC_Channel_1: DAC Channel1 selected +* DAC_Channel_2: DAC Channel2 selected +* DAC_InitStruct:pointer to a DAC_InitTypeDef structure. +* Return : None +*******************************************************************************************/ +void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct) +{ + uint32_t tmpreg1 = 0, tmpreg2 = 0; + + tmpreg1 = DAC->CTLR; + tmpreg1 &= ~(CTLR_CLEAR_MASK << DAC_Channel); + tmpreg2 = (DAC_InitStruct->DAC_Trigger | DAC_InitStruct->DAC_WaveGeneration | + DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude | DAC_InitStruct->DAC_OutputBuffer); + tmpreg1 |= tmpreg2 << DAC_Channel; + DAC->CTLR = tmpreg1; +} + +/****************************************************************************************** +* Function Name : DAC_StructInit +* Description : Fills each DAC_InitStruct member with its default value. +* Input : DAC_InitStruct:pointer to a DAC_InitTypeDef structure which will be initialized. +* Return : None +*******************************************************************************************/ +void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct) +{ + DAC_InitStruct->DAC_Trigger = DAC_Trigger_None; + DAC_InitStruct->DAC_WaveGeneration = DAC_WaveGeneration_None; + DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0; + DAC_InitStruct->DAC_OutputBuffer = DAC_OutputBuffer_Enable; +} + +/****************************************************************************************** +* Function Name : DAC_Cmd +* Description : Enables or disables the specified DAC channel. +* Input : DAC_Channel: the selected DAC channel. +* DAC_Channel_1: DAC Channel1 selected +* DAC_Channel_2: DAC Channel2 selected +* NewState:new state of the DAC channel(ENABLE or DISABLE). +* Return : None +*******************************************************************************************/ +void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DAC->CTLR |= (DAC_EN1 << DAC_Channel); + } + else + { + DAC->CTLR &= ~(DAC_EN1 << DAC_Channel); + } +} + +/****************************************************************************************** +* Function Name : DAC_DMACmd +* Description : Enables or disables the specified DAC channel DMA request. +* Input : DAC_Channel: the selected DAC channel. +* DAC_Channel_1: DAC Channel1 selected +* DAC_Channel_2: DAC Channel2 selected +* NewState:new state of the DAC channel(ENABLE or DISABLE). +* Return : None +*******************************************************************************************/ +void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DAC->CTLR |= (DAC_DMAEN1 << DAC_Channel); + } + else + { + DAC->CTLR &= ~(DAC_DMAEN1 << DAC_Channel); + } +} + +/****************************************************************************************** +* Function Name : DAC_SoftwareTriggerCmd +* Description : Enables or disables the selected DAC channel software trigger. +* Input : DAC_Channel: the selected DAC channel. +* DAC_Channel_1: DAC Channel1 selected +* DAC_Channel_2: DAC Channel2 selected +* NewState:new state of the DAC channel(ENABLE or DISABLE). +* Return : None +*******************************************************************************************/ +void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DAC->SWTR |= (uint32_t)DAC_SWTRIG1 << (DAC_Channel >> 4); + } + else + { + DAC->SWTR &= ~((uint32_t)DAC_SWTRIG1 << (DAC_Channel >> 4)); + } +} + +/****************************************************************************************** +* Function Name : DAC_DualSoftwareTriggerCmd +* Description : Enables or disables the two DAC channel software trigger. +* Input : NewState:new state of the DAC channel(ENABLE or DISABLE). +* Return : None +*******************************************************************************************/ +void DAC_DualSoftwareTriggerCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DAC->SWTR |= DUAL_SWTR_SET ; + } + else + { + DAC->SWTR &= DUAL_SWTR_RESET; + } +} + +/****************************************************************************************** +* Function Name : DAC_WaveGenerationCmd +* Description : Enables or disables the selected DAC channel wave generation. +* Input : DAC_Channel: the selected DAC channel. +* DAC_Channel_1: DAC Channel1 selected +* DAC_Channel_2: DAC Channel2 selected +* DAC_Wave: Specifies the wave type to enable or disable. +* DAC_Wave_Noise: noise wave generation +* DAC_Wave_Triangle: triangle wave generation +* NewState:new state of the DAC channel(ENABLE or DISABLE). +* Return : None +*******************************************************************************************/ +void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DAC->CTLR |= DAC_Wave << DAC_Channel; + } + else + { + DAC->CTLR &= ~(DAC_Wave << DAC_Channel); + } +} + +/****************************************************************************************** +* Function Name : DAC_SetChannel1Data +* Description : Set the specified data holding register value for DAC channel1. +* Input : DAC_Align: Specifies the data alignment for DAC channel1. +* DAC_Align_8b_R: 8bit right data alignment selected +* DAC_Align_12b_L: 12bit left data alignment selected +* DAC_Align_12b_R: 12bit right data alignment selected +* Data : Data to be loaded in the selected data holding register. +* Return : None +*******************************************************************************************/ +void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12R1_OFFSET + DAC_Align; + + *(__IO uint32_t *) tmp = Data; +} + +/****************************************************************************************** +* Function Name : DAC_SetChannel2Data +* Description : Set the specified data holding register value for DAC channel2. +* Input : DAC_Align: Specifies the data alignment for DAC channel1. +* DAC_Align_8b_R: 8bit right data alignment selected +* DAC_Align_12b_L: 12bit left data alignment selected +* DAC_Align_12b_R: 12bit right data alignment selected +* Data : Data to be loaded in the selected data holding register. +* Return : None +*******************************************************************************************/ +void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data) +{ + __IO uint32_t tmp = 0; + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12R2_OFFSET + DAC_Align; + + *(__IO uint32_t *)tmp = Data; +} + +/****************************************************************************************** +* Function Name : DAC_SetDualChannelData +* Description : Set the specified data holding register value for two DAC. +* Input : DAC_Align: Specifies the data alignment for DAC channel1. +* DAC_Align_8b_R: 8bit right data alignment selected +* DAC_Align_12b_L: 12bit left data alignment selected +* DAC_Align_12b_R: 12bit right data alignment selected +* Data1 : Data for DAC Channel1. +* Data2 : Data for DAC Channel2 +* Return : None +*******************************************************************************************/ +void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1) +{ + uint32_t data = 0, tmp = 0; + + if (DAC_Align == DAC_Align_8b_R) + { + data = ((uint32_t)Data2 << 8) | Data1; + } + else + { + data = ((uint32_t)Data2 << 16) | Data1; + } + + tmp = (uint32_t)DAC_BASE; + tmp += DHR12RD_OFFSET + DAC_Align; + + *(__IO uint32_t *)tmp = data; +} + +/****************************************************************************************** +* Function Name : DAC_GetDataOutputValue +* Description : Returns the last data output value of the selected DAC channel. +* Input : DAC_Channel: the selected DAC channel. +* DAC_Channel_1: DAC Channel1 selected +* DAC_Channel_2: DAC Channel2 selected +* Return : None +*******************************************************************************************/ +uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel) +{ + __IO uint32_t tmp = 0; + + tmp = (uint32_t) DAC_BASE ; + tmp += DOR_OFFSET + ((uint32_t)DAC_Channel >> 2); + + return (uint16_t) (*(__IO uint32_t*) tmp); +} + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dbgmcu.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dbgmcu.c new file mode 100644 index 00000000..103ea6a8 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dbgmcu.c @@ -0,0 +1,60 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_dbgmcu.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the DBGMCU firmware functions. +****************************************************************************************/ +#include "ch32v30x_dbgmcu.h" + +/******************************************************************************* +* Function Name : DBGMCU_Config +* Description : Configures the specified peripheral and low power mode behavior +* when the MCU under Debug mode. +* Input : DBGMCU_Periph: specifies the peripheral and low power mode. +* DBGMCU_IWDG_STOP: Debug IWDG stopped when Core is halted +* DBGMCU_WWDG_STOP: Debug WWDG stopped when Core is halted +* DBGMCU_I2C1_SMBUS_TIMEOUT: I2C1 SMBUS timeout mode stopped when Core is halted +* DBGMCU_I2C2_SMBUS_TIMEOUT: I2C2 SMBUS timeout mode stopped when Core is halted +* DBGMCU_TIM1_STOP: TIM1 counter stopped when Core is halted +* DBGMCU_TIM2_STOP: TIM2 counter stopped when Core is halted +* DBGMCU_TIM3_STOP: TIM3 counter stopped when Core is halted +* DBGMCU_TIM4_STOP: TIM4 counter stopped when Core is halted +* DBGMCU_SLEEP: Keep debugger connection during SLEEP mode +* DBGMCU_STOP: Keep debugger connection during STOP mode +* DBGMCU_STANDBY: Keep debugger connection during STANDBY mode +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void DBGMCU_Config(uint32_t DBGMCU_Periph, FunctionalState NewState) +{ + if((DBGMCU_Periph == DBGMCU_SLEEP) || (DBGMCU_Periph == DBGMCU_STOP) || (DBGMCU_Periph == DBGMCU_STANDBY)) + { + if (NewState != DISABLE) + { + DBGMCU->CFGR1 |= DBGMCU_Periph; + } + else + { + DBGMCU->CFGR1 &= ~DBGMCU_Periph; + } + } + else + { + if (NewState != DISABLE) + { + DBGMCU->CFGR0 |= DBGMCU_Periph; + } + else + { + DBGMCU->CFGR0 &= ~DBGMCU_Periph; + } + } +} + + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dma.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dma.c new file mode 100644 index 00000000..e0b78db1 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dma.c @@ -0,0 +1,669 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_dma.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the DMA firmware functions. +*******************************************************************************/ +#include "ch32v30x_dma.h" +#include "ch32v30x_rcc.h" + +/* DMA1 Channelx interrupt pending bit masks */ +#define DMA1_Channel1_IT_Mask ((uint32_t)(DMA_GIF1 | DMA_TCIF1 | DMA_HTIF1 | DMA_TEIF1)) +#define DMA1_Channel2_IT_Mask ((uint32_t)(DMA_GIF2 | DMA_TCIF2 | DMA_HTIF2 | DMA_TEIF2)) +#define DMA1_Channel3_IT_Mask ((uint32_t)(DMA_GIF3 | DMA_TCIF3 | DMA_HTIF3 | DMA_TEIF3)) +#define DMA1_Channel4_IT_Mask ((uint32_t)(DMA_GIF4 | DMA_TCIF4 | DMA_HTIF4 | DMA_TEIF4)) +#define DMA1_Channel5_IT_Mask ((uint32_t)(DMA_GIF5 | DMA_TCIF5 | DMA_HTIF5 | DMA_TEIF5)) +#define DMA1_Channel6_IT_Mask ((uint32_t)(DMA_GIF6 | DMA_TCIF6 | DMA_HTIF6 | DMA_TEIF6)) +#define DMA1_Channel7_IT_Mask ((uint32_t)(DMA_GIF7 | DMA_TCIF7 | DMA_HTIF7 | DMA_TEIF7)) + +/* DMA2 Channelx interrupt pending bit masks */ +#define DMA2_Channel1_IT_Mask ((uint32_t)(DMA_GIF1 | DMA_TCIF1 | DMA_HTIF1 | DMA_TEIF1)) +#define DMA2_Channel2_IT_Mask ((uint32_t)(DMA_GIF2 | DMA_TCIF2 | DMA_HTIF2 | DMA_TEIF2)) +#define DMA2_Channel3_IT_Mask ((uint32_t)(DMA_GIF3 | DMA_TCIF3 | DMA_HTIF3 | DMA_TEIF3)) +#define DMA2_Channel4_IT_Mask ((uint32_t)(DMA_GIF4 | DMA_TCIF4 | DMA_HTIF4 | DMA_TEIF4)) +#define DMA2_Channel5_IT_Mask ((uint32_t)(DMA_GIF5 | DMA_TCIF5 | DMA_HTIF5 | DMA_TEIF5)) +#define DMA2_Channel6_IT_Mask ((uint32_t)(DMA_GIF6 | DMA_TCIF6 | DMA_HTIF6 | DMA_TEIF6)) +#define DMA2_Channel7_IT_Mask ((uint32_t)(DMA_GIF7 | DMA_TCIF7 | DMA_HTIF7 | DMA_TEIF7)) +#define DMA2_Channel8_IT_Mask ((uint32_t)(DMA_GIF8 | DMA_TCIF8 | DMA_HTIF8 | DMA_TEIF8)) +#define DMA2_Channel9_IT_Mask ((uint32_t)(DMA_GIF9 | DMA_TCIF9 | DMA_HTIF9 | DMA_TEIF9)) +#define DMA2_Channel10_IT_Mask ((uint32_t)(DMA_GIF10 | DMA_TCIF10 | DMA_HTIF10 | DMA_TEIF10)) +#define DMA2_Channel11_IT_Mask ((uint32_t)(DMA_GIF11 | DMA_TCIF11 | DMA_HTIF11 | DMA_TEIF11)) + +/* DMA2 FLAG mask */ +#define FLAG_Mask ((uint32_t)0x10000000) +#define DMA2_EXTEN_FLAG_Mask ((uint32_t)0x20000000) + +/* DMA registers Masks */ +#define CFGR_CLEAR_Mask ((uint32_t)0xFFFF800F) + + +/******************************************************************************** +* Function Name : DMA_DeInit +* Description : Deinitializes the DMAy Channelx registers to their default reset +* values. +* Input : DMAy_Channelx:here y can be 1 or 2 to select the DMA and x can be +* 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the +* DMA Channel. +* Return : None +*********************************************************************************/ +void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx) +{ + DMAy_Channelx->CFGR &= (uint16_t)(~DMA_CFGR1_EN); + DMAy_Channelx->CFGR = 0; + DMAy_Channelx->CNTR = 0; + DMAy_Channelx->PADDR = 0; + DMAy_Channelx->MADDR = 0; + if (DMAy_Channelx == DMA1_Channel1) + { + DMA1->INTFCR |= DMA1_Channel1_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel2) + { + DMA1->INTFCR |= DMA1_Channel2_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel3) + { + DMA1->INTFCR |= DMA1_Channel3_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel4) + { + DMA1->INTFCR |= DMA1_Channel4_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel5) + { + DMA1->INTFCR |= DMA1_Channel5_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel6) + { + DMA1->INTFCR |= DMA1_Channel6_IT_Mask; + } + else if (DMAy_Channelx == DMA1_Channel7) + { + DMA1->INTFCR |= DMA1_Channel7_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel1) + { + DMA2->INTFCR |= DMA2_Channel1_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel2) + { + DMA2->INTFCR |= DMA2_Channel2_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel3) + { + DMA2->INTFCR |= DMA2_Channel3_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel4) + { + DMA2->INTFCR |= DMA2_Channel4_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel5) + { + DMA2->INTFCR |= DMA2_Channel5_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel6) + { + DMA2->INTFCR |= DMA2_Channel6_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel7) + { + DMA2->INTFCR |= DMA2_Channel7_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel8) + { + DMA2_EXTEN->INTFCR |= DMA2_Channel8_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel9) + { + DMA2_EXTEN->INTFCR |= DMA2_Channel9_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel10) + { + DMA2_EXTEN->INTFCR |= DMA2_Channel10_IT_Mask; + } + else if (DMAy_Channelx == DMA2_Channel11) + { + DMA2_EXTEN->INTFCR |= DMA2_Channel11_IT_Mask; + } + +} + + +/******************************************************************************** +* Function Name : DMA_Init +* Description : Initializes the DMAy Channelx according to the specified +* parameters in the DMA_InitStruct. +* Input : DMAy_Channelx:here y can be 1 or 2 to select the DMA and x can be +* 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the +* DMA Channel. +* DMA_InitStruct:pointer to a DMA_InitTypeDef structure that +* contains the configuration information for the +* specified DMA Channel. +* Return : None +*********************************************************************************/ +void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct) +{ + uint32_t tmpreg = 0; + + tmpreg = DMAy_Channelx->CFGR; + tmpreg &= CFGR_CLEAR_Mask; + tmpreg |= DMA_InitStruct->DMA_DIR | DMA_InitStruct->DMA_Mode | + DMA_InitStruct->DMA_PeripheralInc | DMA_InitStruct->DMA_MemoryInc | + DMA_InitStruct->DMA_PeripheralDataSize | DMA_InitStruct->DMA_MemoryDataSize | + DMA_InitStruct->DMA_Priority | DMA_InitStruct->DMA_M2M; + + DMAy_Channelx->CFGR = tmpreg; + DMAy_Channelx->CNTR = DMA_InitStruct->DMA_BufferSize; + DMAy_Channelx->PADDR = DMA_InitStruct->DMA_PeripheralBaseAddr; + DMAy_Channelx->MADDR = DMA_InitStruct->DMA_MemoryBaseAddr; +} + + +/******************************************************************************** +* Function Name : DMA_StructInit +* Description : Fills each DMA_InitStruct member with its default value. +* Input : DMA_InitStruct : pointer to a DMA_InitTypeDef structure which will +* 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the +* be initialized. +* Return : None +*********************************************************************************/ +void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct) +{ + DMA_InitStruct->DMA_PeripheralBaseAddr = 0; + DMA_InitStruct->DMA_MemoryBaseAddr = 0; + DMA_InitStruct->DMA_DIR = DMA_DIR_PeripheralSRC; + DMA_InitStruct->DMA_BufferSize = 0; + DMA_InitStruct->DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStruct->DMA_MemoryInc = DMA_MemoryInc_Disable; + DMA_InitStruct->DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStruct->DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStruct->DMA_Mode = DMA_Mode_Normal; + DMA_InitStruct->DMA_Priority = DMA_Priority_Low; + DMA_InitStruct->DMA_M2M = DMA_M2M_Disable; +} + + +/******************************************************************************** +* Function Name : DMA_Cmd +* Description : Enables or disables the specified DMAy Channelx. +* Input : DMAy_Channelx: where y can be 1 or 2 to select the DMA and x can +* be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select +* the DMA Channel. +* NewState : new state of the DMAy Channelx(ENABLE or DISABLE). +* Return : None +*********************************************************************************/ +void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMAy_Channelx->CFGR |= DMA_CFGR1_EN; + } + else + { + DMAy_Channelx->CFGR &= (uint16_t)(~DMA_CFGR1_EN); + } +} + +/******************************************************************************** +* Function Name : DMA_ITConfig +* Description : Enables or disables the specified DMAy Channelx interrupts. +* Input : DMAy_Channelx: where y can be 1 or 2 to select the DMA and x can +* be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select +* the DMA Channel. +* DMA_IT : specifies the DMA interrupts sources to be enabled +* or disabled. +* DMA_IT_TC : Transfer complete interrupt mask +* DMA_IT_HT : Half transfer interrupt mask +* DMA_IT_TE : Transfer error interrupt mask +* NewState : new state of the DMAy Channelx(ENABLE or DISABLE). +* Return : None +*********************************************************************************/ +void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMAy_Channelx->CFGR |= DMA_IT; + } + else + { + DMAy_Channelx->CFGR &= ~DMA_IT; + } +} + +/******************************************************************************** +* Function Name : DMA_SetCurrDataCounter +* Description : Sets the number of data units in the current DMAy Channelx transfer. +* Input : DMAy_Channelx: where y can be 1 or 2 to select the DMA and x can +* be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select +* the DMA Channel. +* DataNumber : The number of data units in the current DMAy Channelx +* transfer. +* Return : None +*********************************************************************************/ +void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber) +{ + DMAy_Channelx->CNTR = DataNumber; +} + +/******************************************************************************** +* Function Name : DMA_GetCurrDataCounter +* Description : Returns the number of remaining data units in the current DMAy Channelx transfer. +* Input : DMAy_Channelx: where y can be 1 or 2 to select the DMA and x can +* be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select +* the DMA Channel. +* Return : DataNumber : The number of remaining data units in the current +* DMAy Channelx transfer. +*********************************************************************************/ +uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx) +{ + return ((uint16_t)(DMAy_Channelx->CNTR)); +} + + +/******************************************************************************** +* Function Name : DMA_GetFlagStatus +* Description : Checks whether the specified DMAy Channelx flag is set or not. +* Input : DMAy_FLAG: specifies the flag to check. +* DMA1_FLAG_GL1: DMA1 Channel1 global flag. +* DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag. +* DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag. +* DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag. +* DMA1_FLAG_GL2: DMA1 Channel2 global flag. +* DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag. +* DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag. +* DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag. +* DMA1_FLAG_GL3: DMA1 Channel3 global flag. +* DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag. +* DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag. +* DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag. +* DMA1_FLAG_GL4: DMA1 Channel4 global flag. +* DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag. +* DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag. +* DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag. +* DMA1_FLAG_GL5: DMA1 Channel5 global flag. +* DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag. +* DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag. +* DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag. +* DMA1_FLAG_GL6: DMA1 Channel6 global flag. +* DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag. +* DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag. +* DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag. +* DMA1_FLAG_GL7: DMA1 Channel7 global flag. +* DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag. +* DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag. +* DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag. +* DMA2_FLAG_GL1: DMA2 Channel1 global flag. +* DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag. +* DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag. +* DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag. +* DMA2_FLAG_GL2: DMA2 Channel2 global flag. +* DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag. +* DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag. +* DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag. +* DMA2_FLAG_GL3: DMA2 Channel3 global flag. +* DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag. +* DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag. +* DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag. +* DMA2_FLAG_GL4: DMA2 Channel4 global flag. +* DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag. +* DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag. +* DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag. +* DMA2_FLAG_GL5: DMA2 Channel5 global flag. +* DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag. +* DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag. +* DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag. +* DMA2_FLAG_GL6: DMA2 Channel6 global flag. +* DMA2_FLAG_TC6: DMA2 Channel6 transfer complete flag. +* DMA2_FLAG_HT6: DMA2 Channel6 half transfer flag. +* DMA2_FLAG_TE6: DMA2 Channel6 transfer error flag. +* DMA2_FLAG_GL7: DMA2 Channel7 global flag. +* DMA2_FLAG_TC7: DMA2 Channel7 transfer complete flag. +* DMA2_FLAG_HT7: DMA2 Channel7 half transfer flag. +* DMA2_FLAG_TE7: DMA2 Channel7 transfer error flag. +* DMA2_FLAG_GL8: DMA2 Channel8 global flag. +* DMA2_FLAG_TC8: DMA2 Channel8 transfer complete flag. +* DMA2_FLAG_HT8: DMA2 Channel8 half transfer flag. +* DMA2_FLAG_TE8: DMA2 Channel8 transfer error flag. +* DMA2_FLAG_GL9: DMA2 Channel9 global flag. +* DMA2_FLAG_TC9: DMA2 Channel9 transfer complete flag. +* DMA2_FLAG_HT9: DMA2 Channel9 half transfer flag. +* DMA2_FLAG_TE9: DMA2 Channel9 transfer error flag. +* DMA2_FLAG_GL10: DMA2 Channel10 global flag. +* DMA2_FLAG_TC10: DMA2 Channel10 transfer complete flag. +* DMA2_FLAG_HT10: DMA2 Channel10 half transfer flag. +* DMA2_FLAG_TE10: DMA2 Channel10 transfer error flag. +* DMA2_FLAG_GL11: DMA2 Channel11 global flag. +* DMA2_FLAG_TC11: DMA2 Channel11 transfer complete flag. +* DMA2_FLAG_HT11: DMA2 Channel11 half transfer flag. +* DMA2_FLAG_TE11: DMA2 Channel11 transfer error flag. +* Return : The new state of DMAy_FLAG (SET or RESET). +*********************************************************************************/ +FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG) +{ + FlagStatus bitstatus = RESET; + uint32_t tmpreg = 0; + + if ((DMAy_FLAG & FLAG_Mask) == FLAG_Mask) + { + tmpreg = DMA2->INTFR ; + } + else if((DMAy_FLAG & DMA2_EXTEN_FLAG_Mask) == DMA2_EXTEN_FLAG_Mask) + { + tmpreg = DMA2_EXTEN->INTFR; + } + else + { + tmpreg = DMA1->INTFR ; + } + + if ((tmpreg & DMAy_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + + +/******************************************************************************** +* Function Name : DMA_ClearFlag +* Description : Clears the DMAy Channelx's pending flags. +* Input : DMAy_FLAG: specifies the flag to check. +* DMA1_FLAG_GL1: DMA1 Channel1 global flag. +* DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag. +* DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag. +* DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag. +* DMA1_FLAG_GL2: DMA1 Channel2 global flag. +* DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag. +* DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag. +* DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag. +* DMA1_FLAG_GL3: DMA1 Channel3 global flag. +* DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag. +* DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag. +* DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag. +* DMA1_FLAG_GL4: DMA1 Channel4 global flag. +* DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag. +* DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag. +* DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag. +* DMA1_FLAG_GL5: DMA1 Channel5 global flag. +* DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag. +* DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag. +* DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag. +* DMA1_FLAG_GL6: DMA1 Channel6 global flag. +* DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag. +* DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag. +* DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag. +* DMA1_FLAG_GL7: DMA1 Channel7 global flag. +* DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag. +* DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag. +* DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag. +* DMA2_FLAG_GL1: DMA2 Channel1 global flag. +* DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag. +* DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag. +* DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag. +* DMA2_FLAG_GL2: DMA2 Channel2 global flag. +* DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag. +* DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag. +* DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag. +* DMA2_FLAG_GL3: DMA2 Channel3 global flag. +* DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag. +* DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag. +* DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag. +* DMA2_FLAG_GL4: DMA2 Channel4 global flag. +* DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag. +* DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag. +* DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag. +* DMA2_FLAG_GL5: DMA2 Channel5 global flag. +* DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag. +* DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag. +* DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag. +* DMA2_FLAG_GL6: DMA2 Channel6 global flag. +* DMA2_FLAG_TC6: DMA2 Channel6 transfer complete flag. +* DMA2_FLAG_HT6: DMA2 Channel6 half transfer flag. +* DMA2_FLAG_TE6: DMA2 Channel6 transfer error flag. +* DMA2_FLAG_GL7: DMA2 Channel7 global flag. +* DMA2_FLAG_TC7: DMA2 Channel7 transfer complete flag. +* DMA2_FLAG_HT7: DMA2 Channel7 half transfer flag. +* DMA2_FLAG_TE7: DMA2 Channel7 transfer error flag. +* DMA2_FLAG_GL8: DMA2 Channel8 global flag. +* DMA2_FLAG_TC8: DMA2 Channel8 transfer complete flag. +* DMA2_FLAG_HT8: DMA2 Channel8 half transfer flag. +* DMA2_FLAG_TE8: DMA2 Channel8 transfer error flag. +* DMA2_FLAG_GL9: DMA2 Channel9 global flag. +* DMA2_FLAG_TC9: DMA2 Channel9 transfer complete flag. +* DMA2_FLAG_HT9: DMA2 Channel9 half transfer flag. +* DMA2_FLAG_TE9: DMA2 Channel9 transfer error flag. +* DMA2_FLAG_GL10: DMA2 Channel10 global flag. +* DMA2_FLAG_TC10: DMA2 Channel10 transfer complete flag. +* DMA2_FLAG_HT10: DMA2 Channel10 half transfer flag. +* DMA2_FLAG_TE10: DMA2 Channel10 transfer error flag. +* DMA2_FLAG_GL11: DMA2 Channel11 global flag. +* DMA2_FLAG_TC11: DMA2 Channel11 transfer complete flag. +* DMA2_FLAG_HT11: DMA2 Channel11 half transfer flag. +* DMA2_FLAG_TE11: DMA2 Channel11 transfer error flag. +* Return : None +*********************************************************************************/ +void DMA_ClearFlag(uint32_t DMAy_FLAG) +{ + if ((DMAy_FLAG & FLAG_Mask) == FLAG_Mask) + { + DMA2->INTFCR = DMAy_FLAG; + } + else if((DMAy_FLAG & DMA2_EXTEN_FLAG_Mask) == DMA2_EXTEN_FLAG_Mask) + { + DMA2_EXTEN->INTFCR = DMAy_FLAG; + } + else + { + DMA1->INTFCR = DMAy_FLAG; + } +} + +/******************************************************************************** +* Function Name : DMA_GetITStatus +* Description : Checks whether the specified DMAy Channelx interrupt has occurred +* or not. +* Input : DMAy_IT: specifies the DMAy interrupt source to check. +* DMA1_IT_GL1: DMA1 Channel1 global flag. +* DMA1_IT_TC1: DMA1 Channel1 transfer complete flag. +* DMA1_IT_HT1: DMA1 Channel1 half transfer flag. +* DMA1_IT_TE1: DMA1 Channel1 transfer error flag. +* DMA1_IT_GL2: DMA1 Channel2 global flag. +* DMA1_IT_TC2: DMA1 Channel2 transfer complete flag. +* DMA1_IT_HT2: DMA1 Channel2 half transfer flag. +* DMA1_IT_TE2: DMA1 Channel2 transfer error flag. +* DMA1_IT_GL3: DMA1 Channel3 global flag. +* DMA1_IT_TC3: DMA1 Channel3 transfer complete flag. +* DMA1_IT_HT3: DMA1 Channel3 half transfer flag. +* DMA1_IT_TE3: DMA1 Channel3 transfer error flag. +* DMA1_IT_GL4: DMA1 Channel4 global flag. +* DMA1_IT_TC4: DMA1 Channel4 transfer complete flag. +* DMA1_IT_HT4: DMA1 Channel4 half transfer flag. +* DMA1_IT_TE4: DMA1 Channel4 transfer error flag. +* DMA1_IT_GL5: DMA1 Channel5 global flag. +* DMA1_IT_TC5: DMA1 Channel5 transfer complete flag. +* DMA1_IT_HT5: DMA1 Channel5 half transfer flag. +* DMA1_IT_TE5: DMA1 Channel5 transfer error flag. +* DMA1_IT_GL6: DMA1 Channel6 global flag. +* DMA1_IT_TC6: DMA1 Channel6 transfer complete flag. +* DMA1_IT_HT6: DMA1 Channel6 half transfer flag. +* DMA1_IT_TE6: DMA1 Channel6 transfer error flag. +* DMA1_IT_GL7: DMA1 Channel7 global flag. +* DMA1_IT_TC7: DMA1 Channel7 transfer complete flag. +* DMA1_IT_HT7: DMA1 Channel7 half transfer flag. +* DMA1_IT_TE7: DMA1 Channel7 transfer error flag. +* DMA2_IT_GL1: DMA2 Channel1 global flag. +* DMA2_IT_TC1: DMA2 Channel1 transfer complete flag. +* DMA2_IT_HT1: DMA2 Channel1 half transfer flag. +* DMA2_IT_TE1: DMA2 Channel1 transfer error flag. +* DMA2_IT_GL2: DMA2 Channel2 global flag. +* DMA2_IT_TC2: DMA2 Channel2 transfer complete flag. +* DMA2_IT_HT2: DMA2 Channel2 half transfer flag. +* DMA2_IT_TE2: DMA2 Channel2 transfer error flag. +* DMA2_IT_GL3: DMA2 Channel3 global flag. +* DMA2_IT_TC3: DMA2 Channel3 transfer complete flag. +* DMA2_IT_HT3: DMA2 Channel3 half transfer flag. +* DMA2_IT_TE3: DMA2 Channel3 transfer error flag. +* DMA2_IT_GL4: DMA2 Channel4 global flag. +* DMA2_IT_TC4: DMA2 Channel4 transfer complete flag. +* DMA2_IT_HT4: DMA2 Channel4 half transfer flag. +* DMA2_IT_TE4: DMA2 Channel4 transfer error flag. +* DMA2_IT_GL5: DMA2 Channel5 global flag. +* DMA2_IT_TC5: DMA2 Channel5 transfer complete flag. +* DMA2_IT_HT5: DMA2 Channel5 half transfer flag. +* DMA2_IT_TE5: DMA2 Channel5 transfer error flag. +* DMA2_IT_GL6: DMA2 Channel6 global flag. +* DMA2_IT_TC6: DMA2 Channel6 transfer complete flag. +* DMA2_IT_HT6: DMA2 Channel6 half transfer flag. +* DMA2_IT_TE6: DMA2 Channel6 transfer error flag. +* DMA2_IT_GL7: DMA2 Channel7 global flag. +* DMA2_IT_TC7: DMA2 Channel7 transfer complete flag. +* DMA2_IT_HT7: DMA2 Channel7 half transfer flag. +* DMA2_IT_TE7: DMA2 Channel7 transfer error flag. +* DMA2_IT_GL8: DMA2 Channel8 global flag. +* DMA2_IT_TC8: DMA2 Channel8 transfer complete flag. +* DMA2_IT_HT8: DMA2 Channel8 half transfer flag. +* DMA2_IT_TE8: DMA2 Channel8 transfer error flag. +* DMA2_IT_GL9: DMA2 Channel9 global flag. +* DMA2_IT_TC9: DMA2 Channel9 transfer complete flag. +* DMA2_IT_HT9: DMA2 Channel9 half transfer flag. +* DMA2_IT_TE9: DMA2 Channel9 transfer error flag. +* DMA2_IT_GL10: DMA2 Channel10 global flag. +* DMA2_IT_TC10: DMA2 Channel10 transfer complete flag. +* DMA2_IT_HT10: DMA2 Channel10 half transfer flag. +* DMA2_IT_TE10: DMA2 Channel10 transfer error flag. +* DMA2_IT_GL11: DMA2 Channel11 global flag. +* DMA2_IT_TC11: DMA2 Channel11 transfer complete flag. +* DMA2_IT_HT11: DMA2 Channel11 half transfer flag. +* DMA2_IT_TE11: DMA2 Channel11 transfer error flag. +* Return : The new state of DMAy_IT (SET or RESET). +*********************************************************************************/ +ITStatus DMA_GetITStatus(uint32_t DMAy_IT) +{ + ITStatus bitstatus = RESET; + uint32_t tmpreg = 0; + + if ((DMAy_IT & FLAG_Mask) == FLAG_Mask) + { + tmpreg = DMA2->INTFR; + } + else if((DMAy_IT & DMA2_EXTEN_FLAG_Mask) == DMA2_EXTEN_FLAG_Mask) + { + tmpreg = DMA2_EXTEN->INTFR; + } + else + { + tmpreg = DMA1->INTFR; + } + + if ((tmpreg & DMAy_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + + +/******************************************************************************** +* Function Name : DMA_ClearITPendingBit +* Description : Clears the DMAy Channelx's interrupt pending bits. +* Input : DMAy_IT: specifies the DMAy interrupt source to clear. +* DMA1_IT_GL1: DMA1 Channel1 global flag. +* DMA1_IT_TC1: DMA1 Channel1 transfer complete flag. +* DMA1_IT_HT1: DMA1 Channel1 half transfer flag. +* DMA1_IT_TE1: DMA1 Channel1 transfer error flag. +* DMA1_IT_GL2: DMA1 Channel2 global flag. +* DMA1_IT_TC2: DMA1 Channel2 transfer complete flag. +* DMA1_IT_HT2: DMA1 Channel2 half transfer flag. +* DMA1_IT_TE2: DMA1 Channel2 transfer error flag. +* DMA1_IT_GL3: DMA1 Channel3 global flag. +* DMA1_IT_TC3: DMA1 Channel3 transfer complete flag. +* DMA1_IT_HT3: DMA1 Channel3 half transfer flag. +* DMA1_IT_TE3: DMA1 Channel3 transfer error flag. +* DMA1_IT_GL4: DMA1 Channel4 global flag. +* DMA1_IT_TC4: DMA1 Channel4 transfer complete flag. +* DMA1_IT_HT4: DMA1 Channel4 half transfer flag. +* DMA1_IT_TE4: DMA1 Channel4 transfer error flag. +* DMA1_IT_GL5: DMA1 Channel5 global flag. +* DMA1_IT_TC5: DMA1 Channel5 transfer complete flag. +* DMA1_IT_HT5: DMA1 Channel5 half transfer flag. +* DMA1_IT_TE5: DMA1 Channel5 transfer error flag. +* DMA1_IT_GL6: DMA1 Channel6 global flag. +* DMA1_IT_TC6: DMA1 Channel6 transfer complete flag. +* DMA1_IT_HT6: DMA1 Channel6 half transfer flag. +* DMA1_IT_TE6: DMA1 Channel6 transfer error flag. +* DMA1_IT_GL7: DMA1 Channel7 global flag. +* DMA1_IT_TC7: DMA1 Channel7 transfer complete flag. +* DMA1_IT_HT7: DMA1 Channel7 half transfer flag. +* DMA1_IT_TE7: DMA1 Channel7 transfer error flag. +* DMA2_IT_GL1: DMA2 Channel1 global flag. +* DMA2_IT_TC1: DMA2 Channel1 transfer complete flag. +* DMA2_IT_HT1: DMA2 Channel1 half transfer flag. +* DMA2_IT_TE1: DMA2 Channel1 transfer error flag. +* DMA2_IT_GL2: DMA2 Channel2 global flag. +* DMA2_IT_TC2: DMA2 Channel2 transfer complete flag. +* DMA2_IT_HT2: DMA2 Channel2 half transfer flag. +* DMA2_IT_TE2: DMA2 Channel2 transfer error flag. +* DMA2_IT_GL3: DMA2 Channel3 global flag. +* DMA2_IT_TC3: DMA2 Channel3 transfer complete flag. +* DMA2_IT_HT3: DMA2 Channel3 half transfer flag. +* DMA2_IT_TE3: DMA2 Channel3 transfer error flag. +* DMA2_IT_GL4: DMA2 Channel4 global flag. +* DMA2_IT_TC4: DMA2 Channel4 transfer complete flag. +* DMA2_IT_HT4: DMA2 Channel4 half transfer flag. +* DMA2_IT_TE4: DMA2 Channel4 transfer error flag. +* DMA2_IT_GL5: DMA2 Channel5 global flag. +* DMA2_IT_TC5: DMA2 Channel5 transfer complete flag. +* DMA2_IT_HT5: DMA2 Channel5 half transfer flag. +* DMA2_IT_TE5: DMA2 Channel5 transfer error flag. +* DMA2_IT_GL6: DMA2 Channel6 global flag. +* DMA2_IT_TC6: DMA2 Channel6 transfer complete flag. +* DMA2_IT_HT6: DMA2 Channel6 half transfer flag. +* DMA2_IT_TE6: DMA2 Channel6 transfer error flag. +* DMA2_IT_GL7: DMA2 Channel7 global flag. +* DMA2_IT_TC7: DMA2 Channel7 transfer complete flag. +* DMA2_IT_HT7: DMA2 Channel7 half transfer flag. +* DMA2_IT_TE7: DMA2 Channel7 transfer error flag. +* DMA2_IT_GL8: DMA2 Channel8 global flag. +* DMA2_IT_TC8: DMA2 Channel8 transfer complete flag. +* DMA2_IT_HT8: DMA2 Channel8 half transfer flag. +* DMA2_IT_TE8: DMA2 Channel8 transfer error flag. +* DMA2_IT_GL9: DMA2 Channel9 global flag. +* DMA2_IT_TC9: DMA2 Channel9 transfer complete flag. +* DMA2_IT_HT9: DMA2 Channel9 half transfer flag. +* DMA2_IT_TE9: DMA2 Channel9 transfer error flag. +* DMA2_IT_GL11: DMA2 Channel10 global flag. +* DMA2_IT_TC11: DMA2 Channel10 transfer complete flag. +* DMA2_IT_HT11: DMA2 Channel10 half transfer flag. +* DMA2_IT_TE11: DMA2 Channel10 transfer error flag. +* DMA2_IT_GL11: DMA2 Channel11 global flag. +* DMA2_IT_TC11: DMA2 Channel11 transfer complete flag. +* DMA2_IT_HT11: DMA2 Channel11 half transfer flag. +* DMA2_IT_TE11: DMA2 Channel11 transfer error flag. +* Return : None +*********************************************************************************/ +void DMA_ClearITPendingBit(uint32_t DMAy_IT) +{ + if ((DMAy_IT & FLAG_Mask) == FLAG_Mask) + { + DMA2->INTFCR = DMAy_IT; + } + else if((DMAy_IT & DMA2_EXTEN_FLAG_Mask) == DMA2_EXTEN_FLAG_Mask) + { + DMA2_EXTEN->INTFCR = DMAy_IT; + } + else + { + DMA1->INTFCR = DMAy_IT; + } +} + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dvp.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dvp.c new file mode 100644 index 00000000..7f2d8c85 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_dvp.c @@ -0,0 +1,118 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_dvp.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the DVP firmware functions. +*******************************************************************************/ +#include "ch32v30x_dvp.h" + + +/******************************************************************************* +* Function Name : DVP_INTCfg +* Description : DVP interrupt configuration +* Input : s: interrupt enable + ENABLE + DISABLE + i: interrupt type + RB_DVP_IE_STP_FRM + RB_DVP_IE_FIFO_OV + RB_DVP_IE_FRM_DONE + RB_DVP_IE_ROW_DONE + RB_DVP_IE_STR_FRM +* Return : None +*******************************************************************************/ +void DVP_INTCfg( uint8_t s, uint8_t i ) +{ + if(s){ + DVP->IER |= i; + } + else{ + DVP->IER &= ~i; + } +} + +/******************************************************************************* +* Function Name : DVP_Mode +* Description : DVP mode +* Input : s: data bit width + RB_DVP_D8_MOD + RB_DVP_D10_MOD + RB_DVP_D12_MOD + i: data mode + Video_Mode + JPEG_Mode +* Return : None +*******************************************************************************/ +void DVP_Mode( uint8_t s, DVP_Data_ModeTypeDef i) +{ + DVP->CR0 &= ~RB_DVP_MSK_DAT_MOD; + + if(s){ + DVP->CR0 |= s; + } + else{ + DVP->CR0 &= ~(3<<4); + } + + if(i){ + DVP->CR0 |= RB_DVP_JPEG; + } + else{ + DVP->CR0 &= ~RB_DVP_JPEG; + } +} + +/******************************************************************************* +* Function Name : DVP_Cfg +* Description : DVP configuration +* Input : s: DMA enable control + DVP_DMA_Enable + DVP_DMA_Disable + i: DVP all clear + DVP_FLAG_FIFO_RESET_Enable + DVP_FLAG_FIFO_RESET_Disable + j: receive reset enable + DVP_RX_RESET_Enable + DVP_RX_RESET_Disable +* Return : None +*******************************************************************************/ +void DVP_Cfg( DVP_DMATypeDef s, DVP_FLAG_FIFO_RESETTypeDef i, DVP_RX_RESETTypeDef j) +{ + switch( s ) + { + case DVP_DMA_Enable: + DVP->CR1 |= RB_DVP_DMA_EN; + break; + case DVP_DMA_Disable: + DVP->CR1 &= ~RB_DVP_DMA_EN; + break; + default: + break; + } + + switch( i ) + { + case DVP_RX_RESET_Enable: + DVP->CR1 |= RB_DVP_ALL_CLR; + break; + case DVP_RX_RESET_Disable: + DVP->CR1 &= ~RB_DVP_ALL_CLR; + break; + default: + break; + } + + switch( j ) + { + case DVP_RX_RESET_Enable: + DVP->CR1 |= RB_DVP_RCV_CLR; + break; + case DVP_RX_RESET_Disable: + DVP->CR1 &= ~RB_DVP_RCV_CLR; + break; + default: + break; + } + +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_eth.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_eth.c new file mode 100644 index 00000000..22b7437a --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_eth.c @@ -0,0 +1,2280 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_eth.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the ETH firmware functions. +*******************************************************************************/ +#include "ch32v30x_eth.h" +#include "ch32v30x_rcc.h" + +ETH_DMADESCTypeDef *DMATxDescToSet; +ETH_DMADESCTypeDef *DMARxDescToGet; +ETH_DMADESCTypeDef *DMAPTPTxDescToSet; +ETH_DMADESCTypeDef *DMAPTPRxDescToGet; + + +/******************************************************************************* +* Function Name : ETH_DeInit +* Description : ETH hardware initialize again. +* Input : None. +* Return : None +*******************************************************************************/ +void ETH_DeInit(void) +{ + RCC_AHBPeriphResetCmd(RCC_AHBPeriph_ETH_MAC, ENABLE); + RCC_AHBPeriphResetCmd(RCC_AHBPeriph_ETH_MAC, DISABLE); +} + +/******************************************************************************* +* Function Name : ETH_StructInit +* Description : Fills each ETH_InitStruct member with its default value. +* Input : ETH_InitStruct: pointer to a ETH_InitTypeDef structure which will be initialized. +* Return : None +*******************************************************************************/ +void ETH_StructInit(ETH_InitTypeDef* ETH_InitStruct) +{ + /*------------------------ MAC -----------------------------------*/ + ETH_InitStruct->ETH_AutoNegotiation = ETH_AutoNegotiation_Disable; + ETH_InitStruct->ETH_Watchdog = ETH_Watchdog_Enable; + ETH_InitStruct->ETH_Jabber = ETH_Jabber_Enable; + ETH_InitStruct->ETH_InterFrameGap = ETH_InterFrameGap_96Bit; + ETH_InitStruct->ETH_CarrierSense = ETH_CarrierSense_Enable; + ETH_InitStruct->ETH_Speed = ETH_Speed_10M; + ETH_InitStruct->ETH_ReceiveOwn = ETH_ReceiveOwn_Enable; + ETH_InitStruct->ETH_LoopbackMode = ETH_LoopbackMode_Disable; + ETH_InitStruct->ETH_Mode = ETH_Mode_HalfDuplex; + ETH_InitStruct->ETH_ChecksumOffload = ETH_ChecksumOffload_Disable; + ETH_InitStruct->ETH_RetryTransmission = ETH_RetryTransmission_Enable; + ETH_InitStruct->ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable; + ETH_InitStruct->ETH_BackOffLimit = ETH_BackOffLimit_10; + ETH_InitStruct->ETH_DeferralCheck = ETH_DeferralCheck_Disable; + ETH_InitStruct->ETH_ReceiveAll = ETH_ReceiveAll_Disable; + ETH_InitStruct->ETH_SourceAddrFilter = ETH_SourceAddrFilter_Disable; + ETH_InitStruct->ETH_PassControlFrames = ETH_PassControlFrames_BlockAll; + ETH_InitStruct->ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Disable; + ETH_InitStruct->ETH_DestinationAddrFilter = ETH_DestinationAddrFilter_Normal; + ETH_InitStruct->ETH_PromiscuousMode = ETH_PromiscuousMode_Disable; + ETH_InitStruct->ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect; + ETH_InitStruct->ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect; + ETH_InitStruct->ETH_HashTableHigh = 0x0; + ETH_InitStruct->ETH_HashTableLow = 0x0; + ETH_InitStruct->ETH_PauseTime = 0x0; + ETH_InitStruct->ETH_ZeroQuantaPause = ETH_ZeroQuantaPause_Disable; + ETH_InitStruct->ETH_PauseLowThreshold = ETH_PauseLowThreshold_Minus4; + ETH_InitStruct->ETH_UnicastPauseFrameDetect = ETH_UnicastPauseFrameDetect_Disable; + ETH_InitStruct->ETH_ReceiveFlowControl = ETH_ReceiveFlowControl_Disable; + ETH_InitStruct->ETH_TransmitFlowControl = ETH_TransmitFlowControl_Disable; + ETH_InitStruct->ETH_VLANTagComparison = ETH_VLANTagComparison_16Bit; + ETH_InitStruct->ETH_VLANTagIdentifier = 0x0; + /*------------------------ DMA -----------------------------------*/ + ETH_InitStruct->ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Disable; + ETH_InitStruct->ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable; + ETH_InitStruct->ETH_FlushReceivedFrame = ETH_FlushReceivedFrame_Enable; + ETH_InitStruct->ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable; + ETH_InitStruct->ETH_TransmitThresholdControl = ETH_TransmitThresholdControl_64Bytes; + ETH_InitStruct->ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable; + ETH_InitStruct->ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable; + ETH_InitStruct->ETH_ReceiveThresholdControl = ETH_ReceiveThresholdControl_64Bytes; + ETH_InitStruct->ETH_SecondFrameOperate = ETH_SecondFrameOperate_Disable; + ETH_InitStruct->ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable; + ETH_InitStruct->ETH_FixedBurst = ETH_FixedBurst_Disable; + ETH_InitStruct->ETH_RxDMABurstLength = ETH_RxDMABurstLength_1Beat; + ETH_InitStruct->ETH_TxDMABurstLength = ETH_TxDMABurstLength_1Beat; + ETH_InitStruct->ETH_DescriptorSkipLength = 0x0; + ETH_InitStruct->ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_1_1; +} + +/******************************************************************************* +* Function Name : ETH_Start +* Description : Enables ENET MAC and DMA reception/transmission. +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_Start(void) +{ + ETH_MACTransmissionCmd(ENABLE); + ETH_FlushTransmitFIFO(); + ETH_MACReceptionCmd(ENABLE); + ETH_DMATransmissionCmd(ENABLE); + ETH_DMAReceptionCmd(ENABLE); +} + +/******************************************************************************* +* Function Name : ETH_HandleTxPkt +* Description : Transmits a packet, from application buffer, pointed by ppkt. +* Input : ppkt: pointer to the application's packet buffer to transmit. +* FrameLength: Tx Packet size. +* Return : ETH_ERROR: in case of Tx desc owned by DMA. +* ETH_SUCCESS: for correct transmission. +*******************************************************************************/ +uint32_t ETH_HandleTxPkt(uint8_t *ppkt, uint16_t FrameLength) +{ + uint32_t offset = 0; + + if((DMATxDescToSet->Status & ETH_DMATxDesc_OWN) != (uint32_t)RESET) + { + return ETH_ERROR; + } + + for(offset=0; offsetBuffer1Addr) + offset)) = (*(ppkt + offset)); + } + + DMATxDescToSet->ControlBufferSize = (FrameLength & ETH_DMATxDesc_TBS1); + DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS ; + DMATxDescToSet->Status |= ETH_DMATxDesc_OWN; + + if((ETH->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET) + { + ETH->DMASR = ETH_DMASR_TBUS; + ETH->DMATPDR = 0; + } + + if((DMATxDescToSet->Status & ETH_DMATxDesc_TCH) != (uint32_t)RESET) + { + DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMATxDescToSet->Buffer2NextDescAddr); + } + else + { + if((DMATxDescToSet->Status & ETH_DMATxDesc_TER) != (uint32_t)RESET) + { + DMATxDescToSet = (ETH_DMADESCTypeDef*) (ETH->DMATDLAR); + } + else + { + DMATxDescToSet = (ETH_DMADESCTypeDef*) ((uint32_t)DMATxDescToSet + 0x10 + ((ETH->DMABMR & ETH_DMABMR_DSL) >> 2)); + } + } + + return ETH_SUCCESS; +} + +/******************************************************************************* +* Function Name : ETH_HandleRxPkt +* Description : Receives a packet and copies it to memory pointed by ppkt. +* Input : ppkt: pointer to the application packet receive buffer. +* Return : ETH_ERROR: if there is error in reception +* framelength: received packet size if packet reception is correct +*******************************************************************************/ +uint32_t ETH_HandleRxPkt(uint8_t *ppkt) +{ + uint32_t offset = 0, framelength = 0; + + if((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) != (uint32_t)RESET) + { + return ETH_ERROR; + } + + if(((DMARxDescToGet->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARxDesc_LS) != (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARxDesc_FS) != (uint32_t)RESET)) + { + framelength = ((DMARxDescToGet->Status & ETH_DMARxDesc_FL) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT) - 4; + + for(offset=0; offsetBuffer1Addr) + offset)); + } + } + else + { + framelength = ETH_ERROR; + } + + DMARxDescToGet->Status = ETH_DMARxDesc_OWN; + + if ((ETH->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) + { + ETH->DMASR = ETH_DMASR_RBUS; + ETH->DMARPDR = 0; + } + + if((DMARxDescToGet->ControlBufferSize & ETH_DMARxDesc_RCH) != (uint32_t)RESET) + { + DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet->Buffer2NextDescAddr); + } + else + { + if((DMARxDescToGet->ControlBufferSize & ETH_DMARxDesc_RER) != (uint32_t)RESET) + { + DMARxDescToGet = (ETH_DMADESCTypeDef*) (ETH->DMARDLAR); + } + else + { + DMARxDescToGet = (ETH_DMADESCTypeDef*) ((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABMR & ETH_DMABMR_DSL) >> 2)); + } + } + + return (framelength); +} + +/******************************************************************************* +* Function Name : ETH_GetRxPktSize +* Description : Get the size of received the received packet. +* Input : None. +* Return : framelength: received packet size +*******************************************************************************/ +uint32_t ETH_GetRxPktSize(void) +{ + uint32_t frameLength = 0; + if(((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARxDesc_LS) != (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARxDesc_FS) != (uint32_t)RESET)) + { + frameLength = ETH_GetDMARxDescFrameLength(DMARxDescToGet); + } + + return frameLength; +} + +/******************************************************************************* +* Function Name : ETH_DropRxPkt +* Description : Drop a Received packet. +* Input : None. +* Return : None +*******************************************************************************/ +void ETH_DropRxPkt(void) +{ + DMARxDescToGet->Status = ETH_DMARxDesc_OWN; + + if((DMARxDescToGet->ControlBufferSize & ETH_DMARxDesc_RCH) != (uint32_t)RESET) + { + DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMARxDescToGet->Buffer2NextDescAddr); + } + else + { + if((DMARxDescToGet->ControlBufferSize & ETH_DMARxDesc_RER) != (uint32_t)RESET) + { + DMARxDescToGet = (ETH_DMADESCTypeDef*) (ETH->DMARDLAR); + } + else + { + DMARxDescToGet = (ETH_DMADESCTypeDef*) ((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABMR & ETH_DMABMR_DSL) >> 2)); + } + } +} + +/******************************************************************************* +* Function Name : ETH_ReadPHYRegister +* Description : Read a PHY register. +* Input : PHYAddress: PHY device address, is the index of one of supported 32 PHY devices. +* PHYReg: PHY register address, is the index of one of the 32 PHY register. +* Return : ETH_ERROR: in case of timeout. +* MAC MIIDR register value: Data read from the selected PHY register. +*******************************************************************************/ +uint16_t ETH_ReadPHYRegister(uint16_t PHYAddress, uint16_t PHYReg) +{ + uint32_t tmpreg = 0; + __IO uint32_t timeout = 0; + + tmpreg = ETH->MACMIIAR; + tmpreg &= ~MACMIIAR_CR_MASK; + tmpreg |=(((uint32_t)PHYAddress<<11) & ETH_MACMIIAR_PA); + tmpreg |=(((uint32_t)PHYReg<<6) & ETH_MACMIIAR_MR); + tmpreg &= ~ETH_MACMIIAR_MW; + tmpreg |= ETH_MACMIIAR_MB; + ETH->MACMIIAR = tmpreg; + + do + { + timeout++; + tmpreg = ETH->MACMIIAR; + } while ((tmpreg & ETH_MACMIIAR_MB) && (timeout < (uint32_t)PHY_READ_TO)); + + if(timeout == PHY_READ_TO) + { + return (uint16_t)ETH_ERROR; + } + + return (uint16_t)(ETH->MACMIIDR); +} + +/******************************************************************************* +* Function Name : ETH_WritePHYRegister +* Description : Write to a PHY register. +* Input : PHYAddress: PHY device address, is the index of one of supported 32 PHY devices. +* PHYReg: PHY register address, is the index of one of the 32 PHY register. +* PHYValue: the value to write. +* Return : ETH_ERROR: in case of timeout. +* ETH_SUCCESS: for correct write +*******************************************************************************/ +uint32_t ETH_WritePHYRegister(uint16_t PHYAddress, uint16_t PHYReg, uint16_t PHYValue) +{ + uint32_t tmpreg = 0; + __IO uint32_t timeout = 0; + + tmpreg = ETH->MACMIIAR; + tmpreg &= ~MACMIIAR_CR_MASK; + tmpreg |=(((uint32_t)PHYAddress<<11) & ETH_MACMIIAR_PA); + tmpreg |=(((uint32_t)PHYReg<<6) & ETH_MACMIIAR_MR); + tmpreg |= ETH_MACMIIAR_MW; + tmpreg |= ETH_MACMIIAR_MB; + ETH->MACMIIDR = PHYValue; + ETH->MACMIIAR = tmpreg; + + do + { + timeout++; + tmpreg = ETH->MACMIIAR; + } while ((tmpreg & ETH_MACMIIAR_MB) && (timeout < (uint32_t)PHY_WRITE_TO)); + + if(timeout >= PHY_WRITE_TO) + { + return ETH_ERROR; + } + + return ETH_SUCCESS; +} + +/******************************************************************************* +* Function Name : ETH_PHYLoopBackCmd +* Description : Enables or disables the PHY loopBack mode. +* Input : PHYAddress: PHY device address, is the index of one of supported 32 PHY devices. +* NewState: new state of the PHY loopBack mode. +* Return : ETH_ERROR: in case of bad PHY configuration. +* ETH_SUCCESS: for correct PHY configuration. +*******************************************************************************/ +uint32_t ETH_PHYLoopBackCmd(uint16_t PHYAddress, FunctionalState NewState) +{ + uint16_t tmpreg = 0; + + tmpreg = ETH_ReadPHYRegister(PHYAddress, PHY_BCR); + + if (NewState != DISABLE) + { + tmpreg |= PHY_Loopback; + } + else + { + tmpreg &= (uint16_t)(~(uint16_t)PHY_Loopback); + } + + if(ETH_WritePHYRegister(PHYAddress, PHY_BCR, tmpreg) != (uint32_t)RESET) + { + return ETH_SUCCESS; + } + else + { + return ETH_ERROR; + } +} + +/******************************************************************************* +* Function Name : ETH_MACTransmissionCmd +* Description : Enables or disables the MAC transmission. +* Input : NewState: new state of the MAC transmission. +* Return : None. +*******************************************************************************/ +void ETH_MACTransmissionCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MACCR |= ETH_MACCR_TE; + } + else + { + ETH->MACCR &= ~ETH_MACCR_TE; + } +} + +/******************************************************************************* +* Function Name : ETH_MACReceptionCmd +* Description : Enables or disables the MAC reception. +* Input : NewState: new state of the MAC reception. +* Return : None. +*******************************************************************************/ +void ETH_MACReceptionCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MACCR |= ETH_MACCR_RE; + } + else + { + ETH->MACCR &= ~ETH_MACCR_RE; + } +} + +/******************************************************************************* +* Function Name : ETH_GetFlowControlBusyStatus +* Description : Enables or disables the MAC reception. +* Input : None +* Return : The new state of flow control busy status bit (SET or RESET).. +*******************************************************************************/ +FlagStatus ETH_GetFlowControlBusyStatus(void) +{ + FlagStatus bitstatus = RESET; + + if ((ETH->MACFCR & ETH_MACFCR_FCBBPA) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_InitiatePauseControlFrame +* Description : Initiate a Pause Control Frame (Full-duplex only). +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_InitiatePauseControlFrame(void) +{ + ETH->MACFCR |= ETH_MACFCR_FCBBPA; +} + +/******************************************************************************* +* Function Name : ETH_BackPressureActivationCmd +* Description : Enables or disables the MAC BackPressure operation activation (Half-duplex only). +* Input : NewState: new state of the MAC BackPressure operation activation. +* Return : None. +*******************************************************************************/ +void ETH_BackPressureActivationCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MACFCR |= ETH_MACFCR_FCBBPA; + } + else + { + ETH->MACFCR &= ~ETH_MACFCR_FCBBPA; + } +} + +/******************************************************************************* +* Function Name : ETH_GetMACFlagStatus +* Description : Checks whether the specified ETHERNET MAC flag is set or not. +* Input : ETH_MAC_FLAG: specifies the flag to check. +* Return : The new state of ETHERNET MAC flag (SET or RESET). +*******************************************************************************/ +FlagStatus ETH_GetMACFlagStatus(uint32_t ETH_MAC_FLAG) +{ + FlagStatus bitstatus = RESET; + + if ((ETH->MACSR & ETH_MAC_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_GetMACITStatus +* Description : Checks whether the specified ETHERNET MAC interrupt has occurred or not. +* Input : ETH_MAC_IT: specifies the interrupt source to check. +* Return : The new state of ETHERNET MAC interrupt (SET or RESET). +*******************************************************************************/ +ITStatus ETH_GetMACITStatus(uint32_t ETH_MAC_IT) +{ + FlagStatus bitstatus = RESET; + + if ((ETH->MACSR & ETH_MAC_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_MACITConfig +* Description : Enables or disables the specified ETHERNET MAC interrupts. +* Input : ETH_MAC_IT: specifies the ETHERNET MAC interrupt sources to be. +* NewState: new state of the specified ETHERNET MAC interrupts. +* Return : None. +*******************************************************************************/ +void ETH_MACITConfig(uint32_t ETH_MAC_IT, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MACIMR &= (~(uint32_t)ETH_MAC_IT); + } + else + { + ETH->MACIMR |= ETH_MAC_IT; + } +} + +/******************************************************************************* +* Function Name : ETH_MACAddressConfig +* Description : Configures the selected MAC address. +* Input : MacAddr: The MAC addres to configure. +* ETH_MAC_Address0 : MAC Address0 +* ETH_MAC_Address1 : MAC Address1 +* ETH_MAC_Address2 : MAC Address2 +* ETH_MAC_Address3 : MAC Address3 +* Addr: Pointer on MAC address buffer data (6 bytes). +* Return : None. +*******************************************************************************/ +void ETH_MACAddressConfig(uint32_t MacAddr, uint8_t *Addr) +{ + uint32_t tmpreg; + + tmpreg = ((uint32_t)Addr[5] << 8) | (uint32_t)Addr[4]; + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + MacAddr)) = tmpreg; + tmpreg = ((uint32_t)Addr[3] << 24) | ((uint32_t)Addr[2] << 16) | ((uint32_t)Addr[1] << 8) | Addr[0]; + + (*(__IO uint32_t *) (ETH_MAC_ADDR_LBASE + MacAddr)) = tmpreg; +} + +/******************************************************************************* +* Function Name : ETH_GetMACAddress +* Description : Get the selected MAC address. +* Input : MacAddr: The MAC address to return. +* ETH_MAC_Address0 : MAC Address0 +* ETH_MAC_Address1 : MAC Address1 +* ETH_MAC_Address2 : MAC Address2 +* ETH_MAC_Address3 : MAC Address3 +* Addr: Pointer on MAC address buffer data (6 bytes). +* Return : None. +*******************************************************************************/ +void ETH_GetMACAddress(uint32_t MacAddr, uint8_t *Addr) +{ + uint32_t tmpreg; + + tmpreg =(*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + MacAddr)); + + Addr[5] = ((tmpreg >> 8) & (uint8_t)0xFF); + Addr[4] = (tmpreg & (uint8_t)0xFF); + tmpreg =(*(__IO uint32_t *) (ETH_MAC_ADDR_LBASE + MacAddr)); + Addr[3] = ((tmpreg >> 24) & (uint8_t)0xFF); + Addr[2] = ((tmpreg >> 16) & (uint8_t)0xFF); + Addr[1] = ((tmpreg >> 8 ) & (uint8_t)0xFF); + Addr[0] = (tmpreg & (uint8_t)0xFF); +} + +/******************************************************************************* +* Function Name : ETH_MACAddressPerfectFilterCmd +* Description : Enables or disables the Address filter module uses the specified. +* Input : MacAddr: The MAC address to return. +* ETH_MAC_Address1 : MAC Address1 +* ETH_MAC_Address2 : MAC Address2 +* ETH_MAC_Address3 : MAC Address3 +* NewState: new state of the specified ETHERNET MAC address use. +* Return : None. +*******************************************************************************/ +void ETH_MACAddressPerfectFilterCmd(uint32_t MacAddr, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + MacAddr)) |= ETH_MACA1HR_AE; + } + else + { + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + MacAddr)) &=(~(uint32_t)ETH_MACA1HR_AE); + } +} + +/******************************************************************************* +* Function Name : ETH_MACAddressFilterConfig +* Description : Set the filter type for the specified ETHERNET MAC address. +* Input : MacAddr: specifies the ETHERNET MAC address. +* ETH_MAC_Address1 : MAC Address1 +* ETH_MAC_Address2 : MAC Address2 +* ETH_MAC_Address3 : MAC Address3 +* Filter: specifies the used frame received field for comparaison. +* ETH_MAC_AddressFilter_SA : MAC Address is used to compare with the +* SA fields of the received frame. +* ETH_MAC_AddressFilter_DA : MAC Address is used to compare with the +* DA fields of the received frame. +* Return : None. +*******************************************************************************/ +void ETH_MACAddressFilterConfig(uint32_t MacAddr, uint32_t Filter) +{ + if (Filter != ETH_MAC_AddressFilter_DA) + { + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + MacAddr)) |= ETH_MACA1HR_SA; + } + else + { + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + MacAddr)) &=(~(uint32_t)ETH_MACA1HR_SA); + } +} + +/******************************************************************************* +* Function Name : ETH_MACAddressMaskBytesFilterConfig +* Description : Set the filter type for the specified ETHERNET MAC address. +* Input : MacAddr: specifies the ETHERNET MAC address. +* ETH_MAC_Address1 : MAC Address1 +* ETH_MAC_Address2 : MAC Address2 +* ETH_MAC_Address3 : MAC Address3 +* MaskByte: specifies the used address bytes for comparaison +* ETH_MAC_AddressMask_Byte5 : Mask MAC Address high reg bits [7:0]. +* ETH_MAC_AddressMask_Byte4 : Mask MAC Address low reg bits [31:24]. +* ETH_MAC_AddressMask_Byte3 : Mask MAC Address low reg bits [23:16]. +* ETH_MAC_AddressMask_Byte2 : Mask MAC Address low reg bits [15:8]. +* ETH_MAC_AddressMask_Byte1 : Mask MAC Address low reg bits [7:0]. +* Return : None. +*******************************************************************************/ +void ETH_MACAddressMaskBytesFilterConfig(uint32_t MacAddr, uint32_t MaskByte) +{ + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + MacAddr)) &=(~(uint32_t)ETH_MACA1HR_MBC); + (*(__IO uint32_t *) (ETH_MAC_ADDR_HBASE + MacAddr)) |= MaskByte; +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescChainInit +* Description : Initializes the DMA Tx descriptors in chain mode. +* Input : DMATxDescTab: Pointer on the first Tx desc list +* TxBuff: Pointer on the first TxBuffer list +* TxBuffCount: Number of the used Tx desc in the list +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescChainInit(ETH_DMADESCTypeDef *DMATxDescTab, uint8_t* TxBuff, uint32_t TxBuffCount) +{ + uint32_t i = 0; + ETH_DMADESCTypeDef *DMATxDesc; + + DMATxDescToSet = DMATxDescTab; + + for(i=0; i < TxBuffCount; i++) + { + DMATxDesc = DMATxDescTab + i; + DMATxDesc->Status = ETH_DMATxDesc_TCH; + DMATxDesc->Buffer1Addr = (uint32_t)(&TxBuff[i*ETH_MAX_PACKET_SIZE]); + + if(i < (TxBuffCount-1)) + { + DMATxDesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab+i+1); + } + else + { + DMATxDesc->Buffer2NextDescAddr = (uint32_t) DMATxDescTab; + } + } + + ETH->DMATDLAR = (uint32_t) DMATxDescTab; +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescRingInit +* Description : Initializes the DMA Tx descriptors in ring mode. +* Input : DMATxDescTab: Pointer on the first Tx desc list. +* TxBuff1: Pointer on the first TxBuffer1 list. +* TxBuff2: Pointer on the first TxBuffer2 list. +* TxBuffCount: Number of the used Tx desc in the list. +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescRingInit(ETH_DMADESCTypeDef *DMATxDescTab, uint8_t *TxBuff1, uint8_t *TxBuff2, uint32_t TxBuffCount) +{ + uint32_t i = 0; + ETH_DMADESCTypeDef *DMATxDesc; + + DMATxDescToSet = DMATxDescTab; + + for(i=0; i < TxBuffCount; i++) + { + DMATxDesc = DMATxDescTab + i; + DMATxDesc->Buffer1Addr = (uint32_t)(&TxBuff1[i*ETH_MAX_PACKET_SIZE]); + DMATxDesc->Buffer2NextDescAddr = (uint32_t)(&TxBuff2[i*ETH_MAX_PACKET_SIZE]); + + if(i == (TxBuffCount-1)) + { + DMATxDesc->Status = ETH_DMATxDesc_TER; + } + } + + ETH->DMATDLAR = (uint32_t) DMATxDescTab; +} + +/******************************************************************************* +* Function Name : ETH_GetDMATxDescFlagStatus +* Description : Checks whether the specified ETHERNET DMA Tx Desc flag is set or not. +* Input : DMATxDesc: pointer on a DMA Tx descriptor +* ETH_DMATxDescFlag: specifies the flag to check. +* TxBuff2: Pointer on the first TxBuffer2 list. +* TxBuffCount: Number of the used Tx desc in the list. +* ETH_DMATxDesc_OWN : OWN bit: descriptor is owned by DMA engine +* ETH_DMATxDesc_IC : Interrupt on completetion +* ETH_DMATxDesc_LS : Last Segment +* ETH_DMATxDesc_FS : First Segment +* ETH_DMATxDesc_DC : Disable CRC +* ETH_DMATxDesc_DP : Disable Pad +* ETH_DMATxDesc_TTSE: Transmit Time Stamp Enable +* ETH_DMATxDesc_TER : Transmit End of Ring +* ETH_DMATxDesc_TCH : Second Address Chained +* ETH_DMATxDesc_TTSS: Tx Time Stamp Status +* ETH_DMATxDesc_IHE : IP Header Error +* ETH_DMATxDesc_ES : Error summary +* ETH_DMATxDesc_JT : Jabber Timeout +* ETH_DMATxDesc_FF : Frame Flushed: DMA/MTL flushed the frame due to SW flush +* ETH_DMATxDesc_PCE : Payload Checksum Error +* ETH_DMATxDesc_LCA : Loss of Carrier: carrier lost during tramsmission +* ETH_DMATxDesc_NC : No Carrier: no carrier signal from the tranceiver +* ETH_DMATxDesc_LCO : Late Collision: transmission aborted due to collision +* ETH_DMATxDesc_EC : Excessive Collision: transmission aborted after 16 collisions +* ETH_DMATxDesc_VF : VLAN Frame +* ETH_DMATxDesc_CC : Collision Count +* ETH_DMATxDesc_ED : Excessive Deferral +* ETH_DMATxDesc_UF : Underflow Error: late data arrival from the memory +* ETH_DMATxDesc_DB : Deferred Bit +* Return : The new state of ETH_DMATxDescFlag (SET or RESET). +*******************************************************************************/ +FlagStatus ETH_GetDMATxDescFlagStatus(ETH_DMADESCTypeDef *DMATxDesc, uint32_t ETH_DMATxDescFlag) +{ + FlagStatus bitstatus = RESET; + + if ((DMATxDesc->Status & ETH_DMATxDescFlag) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_GetDMATxDescCollisionCount +* Description : Returns the specified ETHERNET DMA Tx Desc collision count. +* Input : pointer on a DMA Tx descriptor. +* Return : The Transmit descriptor collision counter value. +*******************************************************************************/ +uint32_t ETH_GetDMATxDescCollisionCount(ETH_DMADESCTypeDef *DMATxDesc) +{ + return ((DMATxDesc->Status & ETH_DMATxDesc_CC) >> ETH_DMATXDESC_COLLISION_COUNTSHIFT); +} + + +/******************************************************************************* +* Function Name : ETH_SetDMATxDescOwnBit +* Description : Set the specified DMA Tx Desc Own bit. +* Input : DMATxDesc: Pointer on a Tx desc +* Return : None +*******************************************************************************/ +void ETH_SetDMATxDescOwnBit(ETH_DMADESCTypeDef *DMATxDesc) +{ + DMATxDesc->Status |= ETH_DMATxDesc_OWN; +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescTransmitITConfig +* Description : Enables or disables the specified DMA Tx Desc Transmit interrupt. +* Input : Pointer on a Tx desc. +* NewState: new state of the DMA Tx Desc transmit interrupt. +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescTransmitITConfig(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMATxDesc->Status |= ETH_DMATxDesc_IC; + } + else + { + DMATxDesc->Status &=(~(uint32_t)ETH_DMATxDesc_IC); + } +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescFrameSegmentConfig +* Description : Enables or disables the specified DMA Tx Desc Transmit interrupt. +* Input : PDMATxDesc: Pointer on a Tx desc. +* ETH_DMATxDesc_FirstSegment : actual Tx desc contain first segment. +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescFrameSegmentConfig(ETH_DMADESCTypeDef *DMATxDesc, uint32_t DMATxDesc_FrameSegment) +{ + DMATxDesc->Status |= DMATxDesc_FrameSegment; +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescChecksumInsertionConfig +* Description : Selects the specified ETHERNET DMA Tx Desc Checksum Insertion. +* Input : DMATxDesc: pointer on a DMA Tx descriptor. +* DMATxDesc_Checksum: specifies is the DMA Tx desc checksum insertion. +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescChecksumInsertionConfig(ETH_DMADESCTypeDef *DMATxDesc, uint32_t DMATxDesc_Checksum) +{ + DMATxDesc->Status |= DMATxDesc_Checksum; +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescCRCCmd +* Description : Enables or disables the DMA Tx Desc CRC. +* Input : DMATxDesc: pointer on a DMA Tx descriptor +* NewState: new state of the specified DMA Tx Desc CRC. +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescCRCCmd(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMATxDesc->Status &= (~(uint32_t)ETH_DMATxDesc_DC); + } + else + { + DMATxDesc->Status |= ETH_DMATxDesc_DC; + } +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescEndOfRingCmd +* Description :Enables or disables the DMA Tx Desc end of ring. +* Input : DMATxDesc: pointer on a DMA Tx descriptor. +* NewState: new state of the specified DMA Tx Desc end of ring. +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescEndOfRingCmd(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMATxDesc->Status |= ETH_DMATxDesc_TER; + } + else + { + DMATxDesc->Status &= (~(uint32_t)ETH_DMATxDesc_TER); + } +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescSecondAddressChainedCmd +* Description : Enables or disables the DMA Tx Desc second address chained. +* Input : DMATxDesc: pointer on a DMA Tx descriptor +* NewState: new state of the specified DMA Tx Desc second address chained. +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescSecondAddressChainedCmd(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMATxDesc->Status |= ETH_DMATxDesc_TCH; + } + else + { + DMATxDesc->Status &=(~(uint32_t)ETH_DMATxDesc_TCH); + } +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescShortFramePaddingCmd +* Description : Enables or disables the DMA Tx Desc padding for frame shorter than 64 bytes. +* Input : DMATxDesc: pointer on a DMA Tx descriptor. +* NewState: new state of the specified DMA Tx Desc padding for frame shorter than 64 bytes. +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescShortFramePaddingCmd(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMATxDesc->Status &= (~(uint32_t)ETH_DMATxDesc_DP); + } + else + { + DMATxDesc->Status |= ETH_DMATxDesc_DP; + } +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescTimeStampCmd +* Description : Enables or disables the DMA Tx Desc time stamp. +* Input : DMATxDesc: pointer on a DMA Tx descriptor +* NewState: new state of the specified DMA Tx Desc time stamp. +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescTimeStampCmd(ETH_DMADESCTypeDef *DMATxDesc, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMATxDesc->Status |= ETH_DMATxDesc_TTSE; + } + else + { + DMATxDesc->Status &=(~(uint32_t)ETH_DMATxDesc_TTSE); + } +} + +/******************************************************************************* +* Function Name : ETH_DMATxDescBufferSizeConfig +* Description : Configures the specified DMA Tx Desc buffer1 and buffer2 sizes. +* Input : DMATxDesc: Pointer on a Tx desc. +* BufferSize1: specifies the Tx desc buffer1 size. +* RxBuff2: Pointer on the first RxBuffer2 list +* BufferSize2: specifies the Tx desc buffer2 size (put "0" if not used). +* Return : None. +*******************************************************************************/ +void ETH_DMATxDescBufferSizeConfig(ETH_DMADESCTypeDef *DMATxDesc, uint32_t BufferSize1, uint32_t BufferSize2) +{ + DMATxDesc->ControlBufferSize |= (BufferSize1 | (BufferSize2 << ETH_DMATXDESC_BUFFER2_SIZESHIFT)); +} + +/******************************************************************************* +* Function Name : ETH_DMARxDescChainInit +* Description : Initializes the DMA Rx descriptors in chain mode. +* Input : DMARxDescTab: Pointer on the first Rx desc list. +* RxBuff: Pointer on the first RxBuffer list. +* RxBuffCount: Number of the used Rx desc in the list. +* Return : None. +*******************************************************************************/ +void ETH_DMARxDescChainInit(ETH_DMADESCTypeDef *DMARxDescTab, uint8_t *RxBuff, uint32_t RxBuffCount) +{ + uint32_t i = 0; + ETH_DMADESCTypeDef *DMARxDesc; + + DMARxDescToGet = DMARxDescTab; + + for(i=0; i < RxBuffCount; i++) + { + DMARxDesc = DMARxDescTab+i; + DMARxDesc->Status = ETH_DMARxDesc_OWN; + DMARxDesc->ControlBufferSize = ETH_DMARxDesc_RCH | (uint32_t)ETH_MAX_PACKET_SIZE; + DMARxDesc->Buffer1Addr = (uint32_t)(&RxBuff[i*ETH_MAX_PACKET_SIZE]); + + if(i < (RxBuffCount-1)) + { + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab+i+1); + } + else + { + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab); + } + } + + ETH->DMARDLAR = (uint32_t) DMARxDescTab; + +} + +/******************************************************************************* +* Function Name : ETH_DMARxDescRingInit +* Description : Initializes the DMA Rx descriptors in ring mode. +* Input : DMARxDescTab: Pointer on the first Rx desc list. +* RxBuff1: Pointer on the first RxBuffer1 list. +* RxBuff2: Pointer on the first RxBuffer2 list +* RxBuffCount: Number of the used Rx desc in the list. +* Return : None. +*******************************************************************************/ +void ETH_DMARxDescRingInit(ETH_DMADESCTypeDef *DMARxDescTab, uint8_t *RxBuff1, uint8_t *RxBuff2, uint32_t RxBuffCount) +{ + uint32_t i = 0; + ETH_DMADESCTypeDef *DMARxDesc; + + DMARxDescToGet = DMARxDescTab; + + for(i=0; i < RxBuffCount; i++) + { + DMARxDesc = DMARxDescTab+i; + DMARxDesc->Status = ETH_DMARxDesc_OWN; + DMARxDesc->ControlBufferSize = ETH_MAX_PACKET_SIZE; + DMARxDesc->Buffer1Addr = (uint32_t)(&RxBuff1[i*ETH_MAX_PACKET_SIZE]); + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(&RxBuff2[i*ETH_MAX_PACKET_SIZE]); + + if(i == (RxBuffCount-1)) + { + DMARxDesc->ControlBufferSize |= ETH_DMARxDesc_RER; + } + } + + ETH->DMARDLAR = (uint32_t) DMARxDescTab; +} + +/******************************************************************************* +* Function Name : ETH_GetDMARxDescFlagStatus +* Description : Checks whether the specified ETHERNET Rx Desc flag is set or not. +* Input : DMARxDesc: pointer on a DMA Rx descriptor. +* ETH_DMARxDescFlag: specifies the flag to check. +* ETH_DMARxDesc_OWN: OWN bit: descriptor is owned by DMA engine +* ETH_DMARxDesc_AFM: DA Filter Fail for the rx frame +* ETH_DMARxDesc_ES: Error summary +* ETH_DMARxDesc_DE: Desciptor error: no more descriptors for receive frame +* ETH_DMARxDesc_SAF: SA Filter Fail for the received frame +* ETH_DMARxDesc_LE: Frame size not matching with length field +* ETH_DMARxDesc_OE: Overflow Error: Frame was damaged due to buffer overflow +* ETH_DMARxDesc_VLAN: VLAN Tag: received frame is a VLAN frame +* ETH_DMARxDesc_FS: First descriptor of the frame +* ETH_DMARxDesc_LS: Last descriptor of the frame +* ETH_DMARxDesc_IPV4HCE: IPC Checksum Error/Giant Frame: Rx Ipv4 header checksum error +* ETH_DMARxDesc_LC: Late collision occurred during reception +* ETH_DMARxDesc_FT: Frame type - Ethernet, otherwise 802.3 +* ETH_DMARxDesc_RWT: Receive Watchdog Timeout: watchdog timer expired during reception +* ETH_DMARxDesc_RE: Receive error: error reported by MII interface +* ETH_DMARxDesc_DE: Dribble bit error: frame contains non int multiple of 8 bits +* ETH_DMARxDesc_CE: CRC error +* ETH_DMARxDesc_MAMPCE: Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum Error +* Return : The new state of ETH_DMARxDescFlag (SET or RESET). +*******************************************************************************/ +FlagStatus ETH_GetDMARxDescFlagStatus(ETH_DMADESCTypeDef *DMARxDesc, uint32_t ETH_DMARxDescFlag) +{ + FlagStatus bitstatus = RESET; + + if ((DMARxDesc->Status & ETH_DMARxDescFlag) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_SetDMARxDescOwnBit +* Description : Set the specified DMA Rx Desc Own bit. +* Input : DMARxDesc: Pointer on a Rx desc +* Return : None. +*******************************************************************************/ +void ETH_SetDMARxDescOwnBit(ETH_DMADESCTypeDef *DMARxDesc) +{ + DMARxDesc->Status |= ETH_DMARxDesc_OWN; +} + +/******************************************************************************* +* Function Name : ETH_GetDMARxDescFrameLength +* Description : Returns the specified DMA Rx Desc frame length. +* Input : DMARxDesc: pointer on a DMA Rx descriptor +* Return : The Rx descriptor received frame length. +*******************************************************************************/ +uint32_t ETH_GetDMARxDescFrameLength(ETH_DMADESCTypeDef *DMARxDesc) +{ + return ((DMARxDesc->Status & ETH_DMARxDesc_FL) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT); +} + +/******************************************************************************* +* Function Name : ETH_DMARxDescReceiveITConfig +* Description : Enables or disables the specified DMA Rx Desc receive interrupt. +* Input : DMARxDesc: Pointer on a Rx desc +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void ETH_DMARxDescReceiveITConfig(ETH_DMADESCTypeDef *DMARxDesc, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMARxDesc->ControlBufferSize &=(~(uint32_t)ETH_DMARxDesc_DIC); + } + else + { + DMARxDesc->ControlBufferSize |= ETH_DMARxDesc_DIC; + } +} + +/******************************************************************************* +* Function Name : ETH_DMARxDescEndOfRingCmd +* Description : Enables or disables the DMA Rx Desc end of ring. +* Input : DMARxDesc: pointer on a DMA Rx descriptor. +* NewState: new state of the specified DMA Rx Desc end of ring. +* Return : None. +*******************************************************************************/ +void ETH_DMARxDescEndOfRingCmd(ETH_DMADESCTypeDef *DMARxDesc, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMARxDesc->ControlBufferSize |= ETH_DMARxDesc_RER; + } + else + { + DMARxDesc->ControlBufferSize &=(~(uint32_t)ETH_DMARxDesc_RER); + } +} + +/******************************************************************************* +* Function Name : ETH_DMARxDescSecondAddressChainedCmd +* Description : Returns the specified ETHERNET DMA Rx Desc buffer size. +* Input : DMARxDesc: pointer on a DMA Rx descriptor +* NewState: new state of the specified DMA Rx Desc second address chained. +* Return : None. +*******************************************************************************/ +void ETH_DMARxDescSecondAddressChainedCmd(ETH_DMADESCTypeDef *DMARxDesc, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + DMARxDesc->ControlBufferSize |= ETH_DMARxDesc_RCH; + } + else + { + DMARxDesc->ControlBufferSize &=(~(uint32_t)ETH_DMARxDesc_RCH); + } +} + +/******************************************************************************* +* Function Name : ETH_GetDMARxDescBufferSize +* Description : Returns the specified ETHERNET DMA Rx Desc buffer size. +* Input : DMARxDesc: pointer on a DMA Rx descriptor. +* DMARxDesc_Buffer: specifies the DMA Rx Desc buffer. +* ETH_DMARxDesc_Buffer1 : DMA Rx Desc Buffer1 +* ETH_DMARxDesc_Buffer2 : DMA Rx Desc Buffer2 +* Return : The Receive descriptor frame length. +*******************************************************************************/ +uint32_t ETH_GetDMARxDescBufferSize(ETH_DMADESCTypeDef *DMARxDesc, uint32_t DMARxDesc_Buffer) +{ + if(DMARxDesc_Buffer != ETH_DMARxDesc_Buffer1) + { + return ((DMARxDesc->ControlBufferSize & ETH_DMARxDesc_RBS2) >> ETH_DMARXDESC_BUFFER2_SIZESHIFT); + } + else + { + return (DMARxDesc->ControlBufferSize & ETH_DMARxDesc_RBS1); + } +} + +/******************************************************************************* +* Function Name : ETH_SoftwareReset +* Description : Resets all MAC subsystem internal registers and logic. +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_SoftwareReset(void) +{ + ETH->DMABMR |= ETH_DMABMR_SR; +} + +/******************************************************************************* +* Function Name : ETH_GetSoftwareResetStatus +* Description : Checks whether the ETHERNET software reset bit is set or not. +* Input : None. +* Return : The new state of DMA Bus Mode register SR bit (SET or RESET). +*******************************************************************************/ +FlagStatus ETH_GetSoftwareResetStatus(void) +{ + FlagStatus bitstatus = RESET; + if((ETH->DMABMR & ETH_DMABMR_SR) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + printf("ETH->DMABMR is:%08x\n",ETH->DMABMR); + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_GetlinkStaus +* Description : Checks whether the internal 10BASE-T PHY is link or not. +* Input : None. +* Return : Internal 10BASE-T PHY is link or not. +*******************************************************************************/ +FlagStatus ETH_GetlinkStaus (void) +{ + FlagStatus bitstatus = RESET; + + if((ETH->DMASR & 0x80000000) != (uint32_t)RESET) + { + bitstatus = PHY_10BASE_T_LINKED; + } + else + { + bitstatus = PHY_10BASE_T_NOT_LINKED; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_GetDMAFlagStatus +* Description : Checks whether the specified ETHERNET DMA flag is set or not. +* Input : ETH_DMA_FLAG: specifies the flag to check. +* ETH_DMA_FLAG_TST : Time-stamp trigger flag +* ETH_DMA_FLAG_PMT : PMT flag +* ETH_DMA_FLAG_MMC : MMC flag +* ETH_DMA_FLAG_DataTransferError : Error bits 0-data buffer, 1-desc. access +* ETH_DMA_FLAG_ReadWriteError : Error bits 0-write trnsf, 1-read transfr +* ETH_DMA_FLAG_AccessError : Error bits 0-Rx DMA, 1-Tx DMA +* ETH_DMA_FLAG_NIS : Normal interrupt summary flag +* ETH_DMA_FLAG_AIS : Abnormal interrupt summary flag +* ETH_DMA_FLAG_ER : Early receive flag +* ETH_DMA_FLAG_FBE : Fatal bus error flag +* ETH_DMA_FLAG_ET : Early transmit flag +* ETH_DMA_FLAG_RWT : Receive watchdog timeout flag +* ETH_DMA_FLAG_RPS : Receive process stopped flag +* ETH_DMA_FLAG_RBU : Receive buffer unavailable flag +* ETH_DMA_FLAG_R : Receive flag +* ETH_DMA_FLAG_TU : Underflow flag +* ETH_DMA_FLAG_RO : Overflow flag +* ETH_DMA_FLAG_TJT : Transmit jabber timeout flag +* ETH_DMA_FLAG_TBU : Transmit buffer unavailable flag +* ETH_DMA_FLAG_TPS : Transmit process stopped flag +* ETH_DMA_FLAG_T : Transmit flag +* Return : The new state of ETH_DMA_FLAG (SET or RESET). +*******************************************************************************/ +FlagStatus ETH_GetDMAFlagStatus(uint32_t ETH_DMA_FLAG) +{ + FlagStatus bitstatus = RESET; + + if ((ETH->DMASR & ETH_DMA_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_DMAClearFlag +* Description : Checks whether the specified ETHERNET DMA interrupt has occured or not. +* Input : ETH_DMA_FLAG: specifies the flag to clear. +* ETH_DMA_FLAG_NIS : Normal interrupt summary flag +* ETH_DMA_FLAG_AIS : Abnormal interrupt summary flag +* ETH_DMA_FLAG_ER : Early receive flag +* ETH_DMA_FLAG_FBE : Fatal bus error flag +* ETH_DMA_FLAG_ETI : Early transmit flag +* ETH_DMA_FLAG_RWT : Receive watchdog timeout flag +* ETH_DMA_FLAG_RPS : Receive process stopped flag +* ETH_DMA_FLAG_RBU : Receive buffer unavailable flag +* ETH_DMA_FLAG_R : Receive flag +* ETH_DMA_FLAG_TU : Transmit Underflow flag +* ETH_DMA_FLAG_RO : Receive Overflow flag +* ETH_DMA_FLAG_TJT : Transmit jabber timeout flag +* ETH_DMA_FLAG_TBU : Transmit buffer unavailable flag +* ETH_DMA_FLAG_TPS : Transmit process stopped flag +* ETH_DMA_FLAG_T : Transmit flag +* Return : None. +*******************************************************************************/ +void ETH_DMAClearFlag(uint32_t ETH_DMA_FLAG) +{ + ETH->DMASR = (uint32_t) ETH_DMA_FLAG; +} + +/******************************************************************************* +* Function Name : ETH_GetDMAITStatus +* Description : Checks whether the specified ETHERNET DMA interrupt has occured or not. +* Input : ETH_DMA_IT: specifies the interrupt pending bit to clear. +* ETH_DMA_IT_TST : Time-stamp trigger interrupt +* ETH_DMA_IT_PMT : PMT interrupt +* ETH_DMA_IT_MMC : MMC interrupt +* ETH_DMA_IT_NIS : Normal interrupt summary +* ETH_DMA_IT_AIS : Abnormal interrupt summary +* ETH_DMA_IT_ER : Early receive interrupt +* ETH_DMA_IT_FBE : Fatal bus error interrupt +* ETH_DMA_IT_ET : Early transmit interrupt +* ETH_DMA_IT_RWT : Receive watchdog timeout interrupt +* ETH_DMA_IT_RPS : Receive process stopped interrupt +* ETH_DMA_IT_RBU : Receive buffer unavailable interrupt +* ETH_DMA_IT_R : Receive interrupt +* ETH_DMA_IT_TU : Underflow interrupt +* ETH_DMA_IT_RO : Overflow interrupt +* ETH_DMA_IT_TJT : Transmit jabber timeout interrupt +* ETH_DMA_IT_TBU : Transmit buffer unavailable interrupt +* ETH_DMA_IT_TPS : Transmit process stopped interrupt +* ETH_DMA_IT_T : Transmit interrupt +* Return : The new state of ETH_DMA_IT (SET or RESET). +*******************************************************************************/ +ITStatus ETH_GetDMAITStatus(uint32_t ETH_DMA_IT) +{ + ITStatus bitstatus = RESET; + + if ((ETH->DMASR & ETH_DMA_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_DMAClearITPendingBit +* Description : Clears the ETHERNETs DMA IT pending bit. +* Input : ETH_DMA_IT: specifies the interrupt pending bit to clear. +* ETH_DMA_IT_NIS : Normal interrupt summary +* ETH_DMA_IT_AIS : Abnormal interrupt summary +* ETH_DMA_IT_ER : Early receive interrupt +* ETH_DMA_IT_FBE : Fatal bus error interrupt +* ETH_DMA_IT_ETI : Early transmit interrupt +* ETH_DMA_IT_RWT : Receive watchdog timeout interrupt +* ETH_DMA_IT_RPS : Receive process stopped interrupt +* ETH_DMA_IT_RBU : Receive buffer unavailable interrupt +* ETH_DMA_IT_R : Receive interrupt +* ETH_DMA_IT_TU : Transmit Underflow interrupt +* ETH_DMA_IT_RO : Receive Overflow interrupt +* ETH_DMA_IT_TJT : Transmit jabber timeout interrupt +* ETH_DMA_IT_TBU : Transmit buffer unavailable interrupt +* ETH_DMA_IT_TPS : Transmit process stopped interrupt +* ETH_DMA_IT_T : Transmit interrupt +* Return : None +*******************************************************************************/ +void ETH_DMAClearITPendingBit(uint32_t ETH_DMA_IT) +{ + ETH->DMASR = (uint32_t) ETH_DMA_IT; +} + +/******************************************************************************* +* Function Name : ETH_GetTransmitProcessState +* Description : Returns the ETHERNET DMA Transmit Process State. +* Input : None. +* Return : The new ETHERNET DMA Transmit Process State: +* ETH_DMA_TransmitProcess_Stopped : Stopped - Reset or Stop Tx Command issued +* ETH_DMA_TransmitProcess_Fetching : Running - fetching the Tx descriptor +* ETH_DMA_TransmitProcess_Waiting : Running - waiting for status +* ETH_DMA_TransmitProcess_Reading : unning - reading the data from host memory +* ETH_DMA_TransmitProcess_Suspended : Suspended - Tx Desciptor unavailabe +* ETH_DMA_TransmitProcess_Closing : Running - closing Rx descriptor +*******************************************************************************/ +uint32_t ETH_GetTransmitProcessState(void) +{ + return ((uint32_t)(ETH->DMASR & ETH_DMASR_TS)); +} + +/******************************************************************************* +* Function Name : ETH_GetReceiveProcessState +* Description : Returns the ETHERNET DMA Receive Process State. +* Input : None. +* Return : The new ETHERNET DMA Receive Process State: +* ETH_DMA_ReceiveProcess_Stopped : Stopped - Reset or Stop Rx Command issued +* ETH_DMA_ReceiveProcess_Fetching : Running - fetching the Rx descriptor +* ETH_DMA_ReceiveProcess_Waiting : Running - waiting for packet +* ETH_DMA_ReceiveProcess_Suspended : Suspended - Rx Desciptor unavailable +* ETH_DMA_ReceiveProcess_Closing : Running - closing descriptor +* ETH_DMA_ReceiveProcess_Queuing : Running - queuing the recieve frame into host memory +*******************************************************************************/ +uint32_t ETH_GetReceiveProcessState(void) +{ + return ((uint32_t)(ETH->DMASR & ETH_DMASR_RS)); +} + +/******************************************************************************* +* Function Name : ETH_FlushTransmitFIFO +* Description : Clears the ETHERNET transmit FIFO. +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_FlushTransmitFIFO(void) +{ + ETH->DMAOMR |= ETH_DMAOMR_FTF; +} + +/******************************************************************************* +* Function Name : ETH_GetFlushTransmitFIFOStatus +* Description : Checks whether the ETHERNET transmit FIFO bit is cleared or not. +* Input : None. +* Return : The new state of ETHERNET flush transmit FIFO bit (SET or RESET). +*******************************************************************************/ +FlagStatus ETH_GetFlushTransmitFIFOStatus(void) +{ + FlagStatus bitstatus = RESET; + if ((ETH->DMAOMR & ETH_DMAOMR_FTF) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_DMATransmissionCmd +* Description : Enables or disables the DMA transmission. +* Input : NewState: new state of the DMA transmission. +* Return : None +*******************************************************************************/ +void ETH_DMATransmissionCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->DMAOMR |= ETH_DMAOMR_ST; + } + else + { + ETH->DMAOMR &= ~ETH_DMAOMR_ST; + } +} + +/******************************************************************************* +* Function Name : ETH_DMAReceptionCmd +* Description : Enables or disables the DMA reception. +* Input : NewState: new state of the DMA reception. +* Return : None +*******************************************************************************/ +void ETH_DMAReceptionCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->DMAOMR |= ETH_DMAOMR_SR; + } + else + { + ETH->DMAOMR &= ~ETH_DMAOMR_SR; + } +} + +/******************************************************************************* +* Function Name : ETH_DMAITConfig +* Description : Enables or disables the specified ETHERNET DMA interrupts. +* Input : ETH_DMA_IT: specifies the ETHERNET DMA interrupt sources to be enabled or disabled. +* ETH_DMA_IT_NIS : Normal interrupt summary +* ETH_DMA_IT_AIS : Abnormal interrupt summary +* ETH_DMA_IT_ER : Early receive interrupt +* ETH_DMA_IT_FBE : Fatal bus error interrupt +* ETH_DMA_IT_ET : Early transmit interrupt +* ETH_DMA_IT_RWT : Receive watchdog timeout interrupt +* ETH_DMA_IT_RPS : Receive process stopped interrupt +* ETH_DMA_IT_RBU : Receive buffer unavailable interrupt +* ETH_DMA_IT_R : Receive interrupt +* ETH_DMA_IT_TU : Underflow interrupt +* ETH_DMA_IT_RO : Overflow interrupt +* ETH_DMA_IT_TJT : Transmit jabber timeout interrupt +* ETH_DMA_IT_TBU : Transmit buffer unavailable interrupt +* ETH_DMA_IT_TPS : Transmit process stopped interrupt +* ETH_DMA_IT_T : Transmit interrupt +* ETH_DMA_Overflow_RxFIFOCounter : Overflow for FIFO Overflow Counter +* ETH_DMA_Overflow_MissedFrameCounter : Overflow for Missed Frame Counter +* NewState: new state of the specified ETHERNET DMA interrupts. +* Return : new state of the specified ETHERNET DMA interrupts. +*******************************************************************************/ +void ETH_DMAITConfig(uint32_t ETH_DMA_IT, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->DMAIER |= ETH_DMA_IT; + } + else + { + ETH->DMAIER &=(~(uint32_t)ETH_DMA_IT); + } +} + +/******************************************************************************* +* Function Name : ETH_GetDMAOverflowStatus +* Description : Checks whether the specified ETHERNET DMA overflow flag is set or not. +* Input : ETH_DMA_Overflow: specifies the DMA overflow flag to check. +* ETH_DMA_Overflow_RxFIFOCounter : Overflow for FIFO Overflow Counter +* ETH_DMA_Overflow_MissedFrameCounter : Overflow for Missed Frame Counter +* Return : The new state of ETHERNET DMA overflow Flag (SET or RESET). +*******************************************************************************/ +FlagStatus ETH_GetDMAOverflowStatus(uint32_t ETH_DMA_Overflow) +{ + FlagStatus bitstatus = RESET; + + if ((ETH->DMAMFBOCR & ETH_DMA_Overflow) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_GetRxOverflowMissedFrameCounter +* Description : Get the ETHERNET DMA Rx Overflow Missed Frame Counter value. +* Input : None. +* Return : The value of Rx overflow Missed Frame Counter. +*******************************************************************************/ +uint32_t ETH_GetRxOverflowMissedFrameCounter(void) +{ + return ((uint32_t)((ETH->DMAMFBOCR & ETH_DMAMFBOCR_MFA)>>ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTERSHIFT)); +} + +/******************************************************************************* +* Function Name : ETH_GetBufferUnavailableMissedFrameCounter +* Description : Get the ETHERNET DMA Buffer Unavailable Missed Frame Counter value. +* Input : None. +* Return : The value of Buffer unavailable Missed Frame Counter. +*******************************************************************************/ +uint32_t ETH_GetBufferUnavailableMissedFrameCounter(void) +{ + return ((uint32_t)(ETH->DMAMFBOCR) & ETH_DMAMFBOCR_MFC); +} + +/******************************************************************************* +* Function Name : ETH_GetCurrentTxDescStartAddress +* Description : Get the ETHERNET DMA DMACHTDR register value. +* Input : None. +* Return : The value of the current Tx desc start address. +*******************************************************************************/ +uint32_t ETH_GetCurrentTxDescStartAddress(void) +{ + return ((uint32_t)(ETH->DMACHTDR)); +} + +/******************************************************************************* +* Function Name : ETH_GetCurrentRxDescStartAddress +* Description : Get the ETHERNET DMA DMACHRDR register value. +* Input : None. +* Return : The value of the current Rx desc start address. +*******************************************************************************/ +uint32_t ETH_GetCurrentRxDescStartAddress(void) +{ + return ((uint32_t)(ETH->DMACHRDR)); +} + +/******************************************************************************* +* Function Name : ETH_GetCurrentTxBufferAddress +* Description : Get the ETHERNET DMA DMACHTBAR register value. +* Input : None. +* Return : The value of the current Tx buffer address. +*******************************************************************************/ +uint32_t ETH_GetCurrentTxBufferAddress(void) +{ + return (DMATxDescToSet->Buffer1Addr); +} + +/******************************************************************************* +* Function Name : ETH_GetCurrentRxBufferAddress +* Description : Get the ETHERNET DMA DMACHRBAR register value. +* Input : None. +* Return : The value of the current Rx buffer address. +*******************************************************************************/ +uint32_t ETH_GetCurrentRxBufferAddress(void) +{ + return ((uint32_t)(ETH->DMACHRBAR)); +} + +/******************************************************************************* +* Function Name : ETH_ResumeDMATransmission +* Description : Resumes the DMA Transmission by writing to the DmaTxPollDemand register +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_ResumeDMATransmission(void) +{ + ETH->DMATPDR = 0; +} + +/******************************************************************************* +* Function Name : ETH_ResumeDMAReception +* Description : Resumes the DMA Transmission by writing to the DmaRxPollDemand register. +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_ResumeDMAReception(void) +{ + ETH->DMARPDR = 0; +} + +/******************************************************************************* +* Function Name : ETH_ResetWakeUpFrameFilterRegisterPointer +* Description : Reset Wakeup frame filter register pointer. +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_ResetWakeUpFrameFilterRegisterPointer(void) +{ + ETH->MACPMTCSR |= ETH_MACPMTCSR_WFFRPR; +} + +/******************************************************************************* +* Function Name : ETH_SetWakeUpFrameFilterRegister +* Description : Populates the remote wakeup frame registers. +* Input : Buffer: Pointer on remote WakeUp Frame Filter Register buffer data (8 words). +* Return : None +*******************************************************************************/ +void ETH_SetWakeUpFrameFilterRegister(uint32_t *Buffer) +{ + uint32_t i = 0; + + for(i =0; iMACRWUFFR = Buffer[i]; + } +} + +/******************************************************************************* +* Function Name : ETH_GlobalUnicastWakeUpCmd +* Description : Enables or disables any unicast packet filtered by the MAC address. +* Input : NewState: new state of the MAC Global Unicast Wake-Up. +* Return : None +*******************************************************************************/ +void ETH_GlobalUnicastWakeUpCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MACPMTCSR |= ETH_MACPMTCSR_GU; + } + else + { + ETH->MACPMTCSR &= ~ETH_MACPMTCSR_GU; + } +} + +/******************************************************************************* +* Function Name : ETH_GetPMTFlagStatus +* Description : Checks whether the specified ETHERNET PMT flag is set or not. +* Input : ETH_PMT_FLAG: specifies the flag to check. +* Return : The new state of ETHERNET PMT Flag (SET or RESET). +*******************************************************************************/ +FlagStatus ETH_GetPMTFlagStatus(uint32_t ETH_PMT_FLAG) +{ + FlagStatus bitstatus = RESET; + + if ((ETH->MACPMTCSR & ETH_PMT_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_WakeUpFrameDetectionCmd +* Description : Enables or disables the MAC Wake-Up Frame Detection. +* Input : NewState: new state of the MAC Wake-Up Frame Detection. +* Return : None. +*******************************************************************************/ +void ETH_WakeUpFrameDetectionCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MACPMTCSR |= ETH_MACPMTCSR_WFE; + } + else + { + ETH->MACPMTCSR &= ~ETH_MACPMTCSR_WFE; + } +} + +/******************************************************************************* +* Function Name : ETH_MagicPacketDetectionCmd +* Description : Enables or disables the MAC Magic Packet Detection. +* Input : NewState: new state of the MAC Magic Packet Detection. +* Return : None. +*******************************************************************************/ +void ETH_MagicPacketDetectionCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MACPMTCSR |= ETH_MACPMTCSR_MPE; + } + else + { + ETH->MACPMTCSR &= ~ETH_MACPMTCSR_MPE; + } +} + +/******************************************************************************* +* Function Name : ETH_PowerDownCmd +* Description : Enables or disables the MAC Power Down. +* Input : NewState: new state of the MAC Power Down. +* Return : None. +*******************************************************************************/ +void ETH_PowerDownCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MACPMTCSR |= ETH_MACPMTCSR_PD; + } + else + { + ETH->MACPMTCSR &= ~ETH_MACPMTCSR_PD; + } +} + +/******************************************************************************* +* Function Name : ETH_MMCCounterFreezeCmd +* Description : Enables or disables the MMC Counter Freeze. +* Input : NewState: new state of the MMC Counter Freeze. +* Return : None. +*******************************************************************************/ +void ETH_MMCCounterFreezeCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MMCCR |= ETH_MMCCR_MCF; + } + else + { + ETH->MMCCR &= ~ETH_MMCCR_MCF; + } +} + +/******************************************************************************* +* Function Name : ETH_MMCResetOnReadCmd +* Description : Enables or disables the MMC Reset On Read. +* Input : NewState: new state of the MMC Reset On Read. +* Return : None. +*******************************************************************************/ +void ETH_MMCResetOnReadCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MMCCR |= ETH_MMCCR_ROR; + } + else + { + ETH->MMCCR &= ~ETH_MMCCR_ROR; + } +} + +/******************************************************************************* +* Function Name : ETH_MMCCounterRolloverCmd +* Description : Enables or disables the MMC Counter Stop Rollover. +* Input : NewState: new state of the MMC Counter Stop Rollover. +* Return : None. +*******************************************************************************/ +void ETH_MMCCounterRolloverCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->MMCCR &= ~ETH_MMCCR_CSR; + } + else + { + ETH->MMCCR |= ETH_MMCCR_CSR; + } +} + +/******************************************************************************* +* Function Name : ETH_MMCCountersReset +* Description : Resets the MMC Counters. +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_MMCCountersReset(void) +{ + ETH->MMCCR |= ETH_MMCCR_CR; +} + +/******************************************************************************* +* Function Name : ETH_MMCITConfig +* Description : Enables or disables the specified ETHERNET MMC interrupts. +* Input : ETH_MMC_IT: specifies the ETHERNET MMC interrupt. +* ETH_MMC_IT_TGF : When Tx good frame counter reaches half the maximum value. +* ETH_MMC_IT_TGFMSC: When Tx good multi col counter reaches half the maximum value. +* ETH_MMC_IT_TGFSC : When Tx good single col counter reaches half the maximum value. +* ETH_MMC_IT_RGUF : When Rx good unicast frames counter reaches half the maximum value. +* ETH_MMC_IT_RFAE : When Rx alignment error counter reaches half the maximum value. +* ETH_MMC_IT_RFCE : When Rx crc error counter reaches half the maximum value. +* Input : NewState: new state of the specified ETHERNET MMC interrupts. +* Return : None. +*******************************************************************************/ +void ETH_MMCITConfig(uint32_t ETH_MMC_IT, FunctionalState NewState) +{ + if ((ETH_MMC_IT & (uint32_t)0x10000000) != (uint32_t)RESET) + { + ETH_MMC_IT &= 0xEFFFFFFF; + + if (NewState != DISABLE) + { + ETH->MMCRIMR &=(~(uint32_t)ETH_MMC_IT); + } + else + { + ETH->MMCRIMR |= ETH_MMC_IT; + } + } + else + { + if (NewState != DISABLE) + { + ETH->MMCTIMR &=(~(uint32_t)ETH_MMC_IT); + } + else + { + ETH->MMCTIMR |= ETH_MMC_IT; + } + } +} + +/******************************************************************************* +* Function Name : ETH_GetMMCITStatus +* Description : Checks whether the specified ETHERNET MMC IT is set or not. +* Input : ETH_MMC_IT: specifies the ETHERNET MMC interrupt. +* ETH_MMC_IT_TxFCGC: When Tx good frame counter reaches half the maximum value. +* ETH_MMC_IT_TxMCGC: When Tx good multi col counter reaches half the maximum value. +* ETH_MMC_IT_TxSCGC: When Tx good single col counter reaches half the maximum value . +* ETH_MMC_IT_RxUGFC: When Rx good unicast frames counter reaches half the maximum value. +* ETH_MMC_IT_RxAEC : When Rx alignment error counter reaches half the maximum value. +* ETH_MMC_IT_RxCEC : When Rx crc error counter reaches half the maximum value. +* Return : The value of ETHERNET MMC IT (SET or RESET). +*******************************************************************************/ +ITStatus ETH_GetMMCITStatus(uint32_t ETH_MMC_IT) +{ + ITStatus bitstatus = RESET; + + if ((ETH_MMC_IT & (uint32_t)0x10000000) != (uint32_t)RESET) + { + if ((((ETH->MMCRIR & ETH_MMC_IT) != (uint32_t)RESET)) && ((ETH->MMCRIMR & ETH_MMC_IT) != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else + { + if ((((ETH->MMCTIR & ETH_MMC_IT) != (uint32_t)RESET)) && ((ETH->MMCRIMR & ETH_MMC_IT) != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_GetMMCRegister +* Description : Get the specified ETHERNET MMC register value. +* Input : ETH_MMCReg: specifies the ETHERNET MMC register. +* ETH_MMCCR : MMC CR register +* ETH_MMCRIR : MMC RIR register +* ETH_MMCTIR : MMC TIR register +* ETH_MMCRIMR : MMC RIMR register +* ETH_MMCTIMR : MMC TIMR register +* ETH_MMCTGFSCCR : MMC TGFSCCR register +* ETH_MMCTGFMSCCR: MMC TGFMSCCR register +* ETH_MMCTGFCR : MMC TGFCR register +* ETH_MMCRFCECR : MMC RFCECR register +* ETH_MMCRFAECR : MMC RFAECR register +* ETH_MMCRGUFCR : MMC RGUFCRregister +* Return : The value of ETHERNET MMC Register value. +*******************************************************************************/ +uint32_t ETH_GetMMCRegister(uint32_t ETH_MMCReg) +{ + return (*(__IO uint32_t *)(ETH_MAC_BASE + ETH_MMCReg)); +} + +/******************************************************************************* +* Function Name : ETH_EnablePTPTimeStampAddend +* Description : Updated the PTP block for fine correction with the Time Stamp Addend register value. +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_EnablePTPTimeStampAddend(void) +{ + ETH->PTPTSCR |= ETH_PTPTSCR_TSARU; +} + +/******************************************************************************* +* Function Name : ETH_EnablePTPTimeStampInterruptTrigger +* Description : Enable the PTP Time Stamp interrupt trigger +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_EnablePTPTimeStampInterruptTrigger(void) +{ + ETH->PTPTSCR |= ETH_PTPTSCR_TSITE; +} + +/******************************************************************************* +* Function Name : ETH_EnablePTPTimeStampUpdate +* Description : Updated the PTP system time with the Time Stamp Update register value. +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_EnablePTPTimeStampUpdate(void) +{ + ETH->PTPTSCR |= ETH_PTPTSCR_TSSTU; +} + +/******************************************************************************* +* Function Name : ETH_InitializePTPTimeStamp +* Description : Initialize the PTP Time Stamp. +* Input : None. +* Return : None. +*******************************************************************************/ +void ETH_InitializePTPTimeStamp(void) +{ + ETH->PTPTSCR |= ETH_PTPTSCR_TSSTI; +} + +/******************************************************************************* +* Function Name : ETH_PTPUpdateMethodConfig +* Description : Selects the PTP Update method. +* Input : UpdateMethod: the PTP Update method. +* Return : None. +*******************************************************************************/ +void ETH_PTPUpdateMethodConfig(uint32_t UpdateMethod) +{ + if (UpdateMethod != ETH_PTP_CoarseUpdate) + { + ETH->PTPTSCR |= ETH_PTPTSCR_TSFCU; + } + else + { + ETH->PTPTSCR &= (~(uint32_t)ETH_PTPTSCR_TSFCU); + } +} + +/******************************************************************************* +* Function Name : ETH_PTPTimeStampCmd +* Description : Enables or disables the PTP time stamp for transmit and receive frames. +* Input : NewState: new state of the PTP time stamp for transmit and receive frames. +* Return : None. +*******************************************************************************/ +void ETH_PTPTimeStampCmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + ETH->PTPTSCR |= ETH_PTPTSCR_TSE; + } + else + { + ETH->PTPTSCR &= (~(uint32_t)ETH_PTPTSCR_TSE); + } +} + +/******************************************************************************* +* Function Name : ETH_GetPTPFlagStatus +* Description : Checks whether the specified ETHERNET PTP flag is set or not. +* Input : ETH_PTP_FLAG: specifies the flag to check. +* Return : The new state of ETHERNET PTP Flag (SET or RESET). +*******************************************************************************/ +FlagStatus ETH_GetPTPFlagStatus(uint32_t ETH_PTP_FLAG) +{ + FlagStatus bitstatus = RESET; + + if ((ETH->PTPTSCR & ETH_PTP_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************* +* Function Name : ETH_SetPTPSubSecondIncrement +* Description : Sets the system time Sub-Second Increment value. +* Input : SubSecondValue: specifies the PTP Sub-Second Increment Register value. +* Return : None. +*******************************************************************************/ +void ETH_SetPTPSubSecondIncrement(uint32_t SubSecondValue) +{ + ETH->PTPSSIR = SubSecondValue; +} + +/******************************************************************************* +* Function Name : ETH_SetPTPTimeStampUpdate +* Description : Sets the Time Stamp update sign and values. +* Input : Sign: specifies the PTP Time update value sign. +* SecondValue: specifies the PTP Time update second value. +* SubSecondValue: specifies the PTP Time update sub-second value. +* Return : None. +*******************************************************************************/ +void ETH_SetPTPTimeStampUpdate(uint32_t Sign, uint32_t SecondValue, uint32_t SubSecondValue) +{ + ETH->PTPTSHUR = SecondValue; + ETH->PTPTSLUR = Sign | SubSecondValue; +} + +/******************************************************************************* +* Function Name : ETH_SetPTPTimeStampAddend +* Description : Sets the Time Stamp Addend value. +* Input : Value: specifies the PTP Time Stamp Addend Register value. +* Return : None. +*******************************************************************************/ +void ETH_SetPTPTimeStampAddend(uint32_t Value) +{ + /* Set the PTP Time Stamp Addend Register */ + ETH->PTPTSAR = Value; +} + +/******************************************************************************* +* Function Name : ETH_SetPTPTargetTime +* Description : Sets the Target Time registers values. +* Input : HighValue: specifies the PTP Target Time High Register value. +* LowValue: specifies the PTP Target Time Low Register value. +* Return : None. +*******************************************************************************/ +void ETH_SetPTPTargetTime(uint32_t HighValue, uint32_t LowValue) +{ + ETH->PTPTTHR = HighValue; + ETH->PTPTTLR = LowValue; +} + +/******************************************************************************* +* Function Name : ETH_GetPTPRegister +* Description : Get the specified ETHERNET PTP register value. +* Input : ETH_PTPReg: specifies the ETHERNET PTP register. +* ETH_PTPTSCR : Sub-Second Increment Register +* ETH_PTPSSIR : Sub-Second Increment Register +* ETH_PTPTSHR : Time Stamp High Register +* ETH_PTPTSLR : Time Stamp Low Register +* ETH_PTPTSHUR : Time Stamp High Update Register +* ETH_PTPTSLUR : Time Stamp Low Update Register +* ETH_PTPTSAR : Time Stamp Addend Register +* ETH_PTPTTHR : Target Time High Register +* ETH_PTPTTLR : Target Time Low Register +* Return : The value of ETHERNET PTP Register value. +*******************************************************************************/ +uint32_t ETH_GetPTPRegister(uint32_t ETH_PTPReg) +{ + return (*(__IO uint32_t *)(ETH_MAC_BASE + ETH_PTPReg)); +} + +/******************************************************************************* +* Function Name : ETH_DMAPTPTxDescChainInit +* Description : Initializes the DMA Tx descriptors in chain mode with PTP. +* Input : DMATxDescTab: Pointer on the first Tx desc list. +* DMAPTPTxDescTab: Pointer on the first PTP Tx desc list. +* TxBuff: Pointer on the first TxBuffer list. +* TxBuffCount: Number of the used Tx desc in the list. +* Return : None. +*******************************************************************************/ +void ETH_DMAPTPTxDescChainInit(ETH_DMADESCTypeDef *DMATxDescTab, ETH_DMADESCTypeDef *DMAPTPTxDescTab, + uint8_t* TxBuff, uint32_t TxBuffCount) +{ + uint32_t i = 0; + ETH_DMADESCTypeDef *DMATxDesc; + + DMATxDescToSet = DMATxDescTab; + DMAPTPTxDescToSet = DMAPTPTxDescTab; + + for(i=0; i < TxBuffCount; i++) + { + DMATxDesc = DMATxDescTab+i; + DMATxDesc->Status = ETH_DMATxDesc_TCH | ETH_DMATxDesc_TTSE; + DMATxDesc->Buffer1Addr =(uint32_t)(&TxBuff[i*ETH_MAX_PACKET_SIZE]); + + if(i < (TxBuffCount-1)) + { + DMATxDesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab+i+1); + } + else + { + DMATxDesc->Buffer2NextDescAddr = (uint32_t) DMATxDescTab; + } + + (&DMAPTPTxDescTab[i])->Buffer1Addr = DMATxDesc->Buffer1Addr; + (&DMAPTPTxDescTab[i])->Buffer2NextDescAddr = DMATxDesc->Buffer2NextDescAddr; + } + + (&DMAPTPTxDescTab[i-1])->Status = (uint32_t) DMAPTPTxDescTab; + + ETH->DMATDLAR = (uint32_t) DMATxDescTab; +} + +/******************************************************************************* +* Function Name : ETH_DMAPTPRxDescChainInit +* Description : Initializes the DMA Rx descriptors in chain mode. +* Input : DMARxDescTab: Pointer on the first Rx desc list. +* DMAPTPRxDescTab: Pointer on the first PTP Rx desc list. +* RxBuff: Pointer on the first RxBuffer list. +* RxBuffCount: Number of the used Rx desc in the list. +* Return : None. +*******************************************************************************/ +void ETH_DMAPTPRxDescChainInit(ETH_DMADESCTypeDef *DMARxDescTab, ETH_DMADESCTypeDef *DMAPTPRxDescTab, + uint8_t *RxBuff, uint32_t RxBuffCount) +{ + uint32_t i = 0; + ETH_DMADESCTypeDef *DMARxDesc; + + DMARxDescToGet = DMARxDescTab; + DMAPTPRxDescToGet = DMAPTPRxDescTab; + + for(i=0; i < RxBuffCount; i++) + { + DMARxDesc = DMARxDescTab+i; + DMARxDesc->Status = ETH_DMARxDesc_OWN; + DMARxDesc->ControlBufferSize = ETH_DMARxDesc_RCH | (uint32_t)ETH_MAX_PACKET_SIZE; + DMARxDesc->Buffer1Addr = (uint32_t)(&RxBuff[i*ETH_MAX_PACKET_SIZE]); + + if(i < (RxBuffCount-1)) + { + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab+i+1); + } + else + { + DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab); + } + + (&DMAPTPRxDescTab[i])->Buffer1Addr = DMARxDesc->Buffer1Addr; + (&DMAPTPRxDescTab[i])->Buffer2NextDescAddr = DMARxDesc->Buffer2NextDescAddr; + } + + (&DMAPTPRxDescTab[i-1])->Status = (uint32_t) DMAPTPRxDescTab; + ETH->DMARDLAR = (uint32_t) DMARxDescTab; +} + +/******************************************************************************* +* Function Name : ETH_HandlePTPTxPkt +* Description : Transmits a packet, from application buffer, pointed by ppkt with Time Stamp values. +* Input : ppkt: pointer to application packet buffer to transmit. +* FrameLength: Tx Packet size. +* PTPTxTab: Pointer on the first PTP Tx table to store Time stamp values. +* Return : ETH_ERROR: in case of Tx desc owned by DMA. +* ETH_SUCCESS: for correct transmission. +*******************************************************************************/ +uint32_t ETH_HandlePTPTxPkt(uint8_t *ppkt, uint16_t FrameLength, uint32_t *PTPTxTab) +{ + uint32_t offset = 0, timeout = 0; + + if((DMATxDescToSet->Status & ETH_DMATxDesc_OWN) != (uint32_t)RESET) + { + return ETH_ERROR; + } + + for(offset=0; offsetBuffer1Addr) + offset)) = (*(ppkt + offset)); + } + + DMATxDescToSet->ControlBufferSize = (FrameLength & (uint32_t)0x1FFF); + DMATxDescToSet->Status |= ETH_DMATxDesc_LS | ETH_DMATxDesc_FS; + DMATxDescToSet->Status |= ETH_DMATxDesc_OWN; + + if ((ETH->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET) + { + ETH->DMASR = ETH_DMASR_TBUS; + ETH->DMATPDR = 0; + } + + do + { + timeout++; + } while (!(DMATxDescToSet->Status & ETH_DMATxDesc_TTSS) && (timeout < 0xFFFF)); + + if(timeout == PHY_READ_TO) + { + return ETH_ERROR; + } + + DMATxDescToSet->Status &= ~ETH_DMATxDesc_TTSS; + *PTPTxTab++ = DMATxDescToSet->Buffer1Addr; + *PTPTxTab = DMATxDescToSet->Buffer2NextDescAddr; + + if((DMATxDescToSet->Status & ETH_DMATxDesc_TCH) != (uint32_t)RESET) + { + DMATxDescToSet = (ETH_DMADESCTypeDef*) (DMAPTPTxDescToSet->Buffer2NextDescAddr); + if(DMAPTPTxDescToSet->Status != 0) + { + DMAPTPTxDescToSet = (ETH_DMADESCTypeDef*) (DMAPTPTxDescToSet->Status); + } + else + { + DMAPTPTxDescToSet++; + } + } + else + { + if((DMATxDescToSet->Status & ETH_DMATxDesc_TER) != (uint32_t)RESET) + { + DMATxDescToSet = (ETH_DMADESCTypeDef*) (ETH->DMATDLAR); + DMAPTPTxDescToSet = (ETH_DMADESCTypeDef*) (ETH->DMATDLAR); + } + else + { + DMATxDescToSet = (ETH_DMADESCTypeDef*) ((uint32_t)DMATxDescToSet + 0x10 + ((ETH->DMABMR & ETH_DMABMR_DSL) >> 2)); + DMAPTPTxDescToSet = (ETH_DMADESCTypeDef*) ((uint32_t)DMAPTPTxDescToSet + 0x10 + ((ETH->DMABMR & ETH_DMABMR_DSL) >> 2)); + } + } + + return ETH_SUCCESS; +} + +/******************************************************************************* +* Function Name : ETH_HandlePTPRxPkt +* Description : Receives a packet and copies it to memory pointed by ppkt with Time Stamp values. +* Input : ppkt: pointer to application packet receive buffer. +* PTPRxTab: Pointer on the first PTP Rx table to store Time stamp values. +* Return : ETH_ERROR: if there is error in reception. +* framelength: received packet size if packet reception is correct +*******************************************************************************/ +uint32_t ETH_HandlePTPRxPkt(uint8_t *ppkt, uint32_t *PTPRxTab) +{ + uint32_t offset = 0, framelength = 0; + + if((DMARxDescToGet->Status & ETH_DMARxDesc_OWN) != (uint32_t)RESET) + { + return ETH_ERROR; + } + if(((DMARxDescToGet->Status & ETH_DMARxDesc_ES) == (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARxDesc_LS) != (uint32_t)RESET) && + ((DMARxDescToGet->Status & ETH_DMARxDesc_FS) != (uint32_t)RESET)) + { + framelength = ((DMARxDescToGet->Status & ETH_DMARxDesc_FL) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT) - 4; + + for(offset=0; offsetBuffer1Addr) + offset)); + } + } + else + { + framelength = ETH_ERROR; + } + + if ((ETH->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) + { + ETH->DMASR = ETH_DMASR_RBUS; + ETH->DMARPDR = 0; + } + + *PTPRxTab++ = DMARxDescToGet->Buffer1Addr; + *PTPRxTab = DMARxDescToGet->Buffer2NextDescAddr; + DMARxDescToGet->Status |= ETH_DMARxDesc_OWN; + + if((DMARxDescToGet->ControlBufferSize & ETH_DMARxDesc_RCH) != (uint32_t)RESET) + { + DMARxDescToGet = (ETH_DMADESCTypeDef*) (DMAPTPRxDescToGet->Buffer2NextDescAddr); + if(DMAPTPRxDescToGet->Status != 0) + { + DMAPTPRxDescToGet = (ETH_DMADESCTypeDef*) (DMAPTPRxDescToGet->Status); + } + else + { + DMAPTPRxDescToGet++; + } + } + else + { + if((DMARxDescToGet->ControlBufferSize & ETH_DMARxDesc_RER) != (uint32_t)RESET) + { + DMARxDescToGet = (ETH_DMADESCTypeDef*) (ETH->DMARDLAR); + } + else + { + DMARxDescToGet = (ETH_DMADESCTypeDef*) ((uint32_t)DMARxDescToGet + 0x10 + ((ETH->DMABMR & ETH_DMABMR_DSL) >> 2)); + } + } + + return (framelength); +} + + +/******************************************************************************* +* Function Name : RGMII_TXC_Delay +* Description : Delay time. +* Input : None +* Return : None +*******************************************************************************/ +void RGMII_TXC_Delay(uint8_t clock_polarity,uint8_t delay_time) +{ + if(clock_polarity){ + ETH->MACCR |= (uint32_t)(1<<1); + } + else{ + ETH->MACCR &=~(uint32_t)(1<<1); + } + if(delay_time<=7){ + ETH->MACCR |= (uint32_t)(delay_time<<29); + } + else{ + printf("Error:delay_time is out of range!\n"); + } +} + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_exti.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_exti.c new file mode 100644 index 00000000..472cf610 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_exti.c @@ -0,0 +1,157 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_exti.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the EXTI firmware functions. +***************************************************************************************/ +#include "ch32v30x_exti.h" + +/* No interrupt selected */ +#define EXTI_LINENONE ((uint32_t)0x00000) + +/******************************************************************************** +* Function Name : EXTI_DeInit +* Description : Deinitializes the EXTI peripheral registers to their default +* reset values. +* Input : None +* Return : None +*********************************************************************************/ +void EXTI_DeInit(void) +{ + EXTI->INTENR = 0x00000000; + EXTI->EVENR = 0x00000000; + EXTI->RTENR = 0x00000000; + EXTI->FTENR = 0x00000000; + EXTI->INTFR = 0x000FFFFF; +} + +/******************************************************************************** +* Function Name : EXTI_Init +* Description : Initializes the EXTI peripheral according to the specified +* parameters in the EXTI_InitStruct. +* Input : EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure +* Return : None +*********************************************************************************/ +void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct) +{ + uint32_t tmp = 0; + + tmp = (uint32_t)EXTI_BASE; + if (EXTI_InitStruct->EXTI_LineCmd != DISABLE) + { + EXTI->INTENR &= ~EXTI_InitStruct->EXTI_Line; + EXTI->EVENR &= ~EXTI_InitStruct->EXTI_Line; + tmp += EXTI_InitStruct->EXTI_Mode; + *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line; + EXTI->RTENR &= ~EXTI_InitStruct->EXTI_Line; + EXTI->FTENR &= ~EXTI_InitStruct->EXTI_Line; + if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling) + { + EXTI->RTENR |= EXTI_InitStruct->EXTI_Line; + EXTI->FTENR |= EXTI_InitStruct->EXTI_Line; + } + else + { + tmp = (uint32_t)EXTI_BASE; + tmp += EXTI_InitStruct->EXTI_Trigger; + *(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line; + } + } + else + { + tmp += EXTI_InitStruct->EXTI_Mode; + *(__IO uint32_t *) tmp &= ~EXTI_InitStruct->EXTI_Line; + } +} + +/******************************************************************************** +* Function Name : EXTI_StructInit +* Description : Fills each EXTI_InitStruct member with its reset value. +* Input : EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure +* Return : None +*********************************************************************************/ +void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct) +{ + EXTI_InitStruct->EXTI_Line = EXTI_LINENONE; + EXTI_InitStruct->EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStruct->EXTI_Trigger = EXTI_Trigger_Falling; + EXTI_InitStruct->EXTI_LineCmd = DISABLE; +} + +/******************************************************************************** +* Function Name : EXTI_GenerateSWInterrupt +* Description : Generates a Software interrupt. +* Input : EXTI_Line: specifies the EXTI lines to be enabled or disabled. +* Return : None +*********************************************************************************/ +void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line) +{ + EXTI->SWIEVR |= EXTI_Line; +} + +/******************************************************************************** +* Function Name : EXTI_GetFlagStatus +* Description : Checks whether the specified EXTI line flag is set or not. +* Input : EXTI_Line: specifies the EXTI lines to be enabled or disabled. +* Return : The new state of EXTI_Line (SET or RESET). +*********************************************************************************/ +FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line) +{ + FlagStatus bitstatus = RESET; + if ((EXTI->INTFR & EXTI_Line) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************** +* Function Name : EXTI_ClearFlag +* Description : Clears the EXTI's line pending flags. +* Input : EXTI_Line: specifies the EXTI lines to be enabled or disabled. +* Return : None +*********************************************************************************/ +void EXTI_ClearFlag(uint32_t EXTI_Line) +{ + EXTI->INTFR = EXTI_Line; +} + +/******************************************************************************** +* Function Name : EXTI_GetITStatus +* Description : Checks whether the specified EXTI line is asserted or not. +* Input : EXTI_Line: specifies the EXTI lines to be enabled or disabled. +* Return : The new state of EXTI_Line (SET or RESET). +*********************************************************************************/ +ITStatus EXTI_GetITStatus(uint32_t EXTI_Line) +{ + ITStatus bitstatus = RESET; + uint32_t enablestatus = 0; + + enablestatus = EXTI->INTENR & EXTI_Line; + if (((EXTI->INTFR & EXTI_Line) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************** +* Function Name : EXTI_ClearITPendingBit +* Description : Clears the EXTI's line pending bits. +* Input : EXTI_Line: specifies the EXTI lines to be enabled or disabled. +* Return : None +*********************************************************************************/ +void EXTI_ClearITPendingBit(uint32_t EXTI_Line) +{ + EXTI->INTFR = EXTI_Line; +} + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_flash.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_flash.c new file mode 100644 index 00000000..96e7e39b --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_flash.c @@ -0,0 +1,895 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_flash.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the FLASH firmware functions. +***************************************************************************************/ +#include "ch32v30x_flash.h" + +/* Flash Access Control Register bits */ +#define ACR_LATENCY_Mask ((uint32_t)0x00000038) +#define ACR_HLFCYA_Mask ((uint32_t)0xFFFFFFF7) +#define ACR_PRFTBE_Mask ((uint32_t)0xFFFFFFEF) + +/* Flash Access Control Register bits */ +#define ACR_PRFTBS_Mask ((uint32_t)0x00000020) + +/* Flash Control Register bits */ +#define CR_PG_Set ((uint32_t)0x00000001) +#define CR_PG_Reset ((uint32_t)0x00001FFE) +#define CR_PER_Set ((uint32_t)0x00000002) +#define CR_PER_Reset ((uint32_t)0x00001FFD) +#define CR_MER_Set ((uint32_t)0x00000004) +#define CR_MER_Reset ((uint32_t)0x00001FFB) +#define CR_OPTPG_Set ((uint32_t)0x00000010) +#define CR_OPTPG_Reset ((uint32_t)0x00001FEF) +#define CR_OPTER_Set ((uint32_t)0x00000020) +#define CR_OPTER_Reset ((uint32_t)0x00001FDF) +#define CR_STRT_Set ((uint32_t)0x00000040) +#define CR_LOCK_Set ((uint32_t)0x00000080) +#define CR_FAST_LOCK_Set ((uint32_t)0x00008000) +#define CR_PAGE_PG ((uint32_t)0x00010000) +#define CR_PAGE_ER ((uint32_t)0x00020000) +#define CR_BER32 ((uint32_t)0x00040000) +#define CR_BER64 ((uint32_t)0x00080000) +#define CR_PG_STRT ((uint32_t)0x00200000) + +/* FLASH Status Register bits */ +#define SR_BSY ((uint32_t)0x00000001) +#define SR_WR_BSY ((uint32_t)0x00000002) +#define SR_WRPRTERR ((uint32_t)0x00000010) +#define SR_EOP ((uint32_t)0x00000020) + +/* FLASH Mask */ +#define RDPRT_Mask ((uint32_t)0x00000002) +#define WRP0_Mask ((uint32_t)0x000000FF) +#define WRP1_Mask ((uint32_t)0x0000FF00) +#define WRP2_Mask ((uint32_t)0x00FF0000) +#define WRP3_Mask ((uint32_t)0xFF000000) +#define OB_USER_BFB2 ((uint16_t)0x0008) + +/* FLASH Keys */ +#define RDP_Key ((uint16_t)0x00A5) +#define FLASH_KEY1 ((uint32_t)0x45670123) +#define FLASH_KEY2 ((uint32_t)0xCDEF89AB) + +/* FLASH BANK address */ +#define FLASH_BANK1_END_ADDRESS ((uint32_t)0x807FFFF) + +/* Delay definition */ +#define EraseTimeout ((uint32_t)0x000B0000) +#define ProgramTimeout ((uint32_t)0x00005000) + +/******************************************************************************** +* Function Name : FLASH_SetLatency +* Description : Sets the code latency value. +* Input : FLASH_Latency: specifies the FLASH Latency value. +* FLASH_Latency_0: FLASH Zero Latency cycle +* FLASH_Latency_1: FLASH One Latency cycle +* FLASH_Latency_2: FLASH Two Latency cycles +* Return : None +*********************************************************************************/ +void FLASH_SetLatency(uint32_t FLASH_Latency) +{ + uint32_t tmpreg = 0; + + tmpreg = FLASH->ACTLR; + tmpreg &= ACR_LATENCY_Mask; + tmpreg |= FLASH_Latency; + FLASH->ACTLR = tmpreg; +} + + +/******************************************************************************** +* Function Name : FLASH_HalfCycleAccessCmd +* Description : Enables or disables the Half cycle flash access. +* Input : FLASH_HalfCycleAccess: specifies the FLASH Half cycle Access mode. +* FLASH_HalfCycleAccess_Enable: FLASH Half Cycle Enable +* FLASH_HalfCycleAccess_Disable: FLASH Half Cycle Disable +* Return : None +*********************************************************************************/ +void FLASH_HalfCycleAccessCmd(uint32_t FLASH_HalfCycleAccess) +{ + FLASH->ACTLR &= ACR_HLFCYA_Mask; + FLASH->ACTLR |= FLASH_HalfCycleAccess; +} + +/******************************************************************************** +* Function Name : FLASH_PrefetchBufferCmd +* Description : Enables or disables the Prefetch Buffer. +* Input : FLASH_PrefetchBuffer: specifies the Prefetch buffer status. +* FLASH_PrefetchBuffer_Enable: FLASH Prefetch Buffer Enable +* FLASH_PrefetchBuffer_Disable: FLASH Prefetch Buffer Disable +* Return : None +*********************************************************************************/ +void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer) +{ + FLASH->ACTLR &= ACR_PRFTBE_Mask; + FLASH->ACTLR |= FLASH_PrefetchBuffer; +} + + +/******************************************************************************** +* Function Name : FLASH_Unlock +* Description : Unlocks the FLASH Program Erase Controller. +* Input : None +* Return : None +*********************************************************************************/ +void FLASH_Unlock(void) +{ + /* Authorize the FPEC of Bank1 Access */ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; +} + + +/******************************************************************************** +* Function Name : FLASH_UnlockBank1 +* Description : Unlocks the FLASH Bank1 Program Erase Controller. +* equivalent to FLASH_Unlock function. +* Input : None +* Return : None +*********************************************************************************/ +void FLASH_UnlockBank1(void) +{ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; +} + +/******************************************************************************** +* Function Name : FLASH_Lock +* Description : Locks the FLASH Program Erase Controller. +* Input : None +* Return : None +*********************************************************************************/ +void FLASH_Lock(void) +{ + FLASH->CTLR |= CR_LOCK_Set; +} + +/******************************************************************************** +* Function Name : FLASH_LockBank1 +* Description : Locks the FLASH Bank1 Program Erase Controller. +* Input : None +* Return : None +*********************************************************************************/ +void FLASH_LockBank1(void) +{ + FLASH->CTLR |= CR_LOCK_Set; +} + + +/******************************************************************************** +* Function Name : FLASH_ErasePage +* Description : Erases a specified FLASH page(page size 4KB). +* Input : Page_Address: The page address to be erased. +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_ErasePage(uint32_t Page_Address) +{ + FLASH_Status status = FLASH_COMPLETE; + + status = FLASH_WaitForLastOperation(EraseTimeout); + + if(status == FLASH_COMPLETE) + { + FLASH->CTLR|= CR_PER_Set; + FLASH->ADDR = Page_Address; + FLASH->CTLR|= CR_STRT_Set; + + status = FLASH_WaitForLastOperation(EraseTimeout); + + FLASH->CTLR &= CR_PER_Reset; + } + + return status; +} + + +/******************************************************************************** +* Function Name : FLASH_EraseAllPages +* Description : Erases all FLASH pages. +* Input : None +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_EraseAllPages(void) +{ + FLASH_Status status = FLASH_COMPLETE; + + status = FLASH_WaitForLastOperation(EraseTimeout); + if(status == FLASH_COMPLETE) + { + FLASH->CTLR |= CR_MER_Set; + FLASH->CTLR |= CR_STRT_Set; + + status = FLASH_WaitForLastOperation(EraseTimeout); + + FLASH->CTLR &= CR_MER_Reset; + } + + return status; +} + +/******************************************************************************** +* Function Name : FLASH_EraseAllBank1Pages +* Description : Erases all Bank1 FLASH pages. +* Input : None +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_EraseAllBank1Pages(void) +{ + FLASH_Status status = FLASH_COMPLETE; + status = FLASH_WaitForLastBank1Operation(EraseTimeout); + + if(status == FLASH_COMPLETE) + { + FLASH->CTLR |= CR_MER_Set; + FLASH->CTLR |= CR_STRT_Set; + + status = FLASH_WaitForLastBank1Operation(EraseTimeout); + + FLASH->CTLR &= CR_MER_Reset; + } + return status; +} + +/******************************************************************************** +* Function Name : FLASH_EraseOptionBytes +* Description : Erases the FLASH option bytes. +* Input : None +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_EraseOptionBytes(void) +{ + uint16_t rdptmp = RDP_Key; + + FLASH_Status status = FLASH_COMPLETE; + if(FLASH_GetReadOutProtectionStatus() != RESET) + { + rdptmp = 0x00; + } + status = FLASH_WaitForLastOperation(EraseTimeout); + if(status == FLASH_COMPLETE) + { + FLASH->OBKEYR = FLASH_KEY1; + FLASH->OBKEYR = FLASH_KEY2; + + FLASH->CTLR |= CR_OPTER_Set; + FLASH->CTLR |= CR_STRT_Set; + status = FLASH_WaitForLastOperation(EraseTimeout); + + if(status == FLASH_COMPLETE) + { + FLASH->CTLR &= CR_OPTER_Reset; + FLASH->CTLR |= CR_OPTPG_Set; + OB->RDPR = (uint16_t)rdptmp; + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status != FLASH_TIMEOUT) + { + FLASH->CTLR &= CR_OPTPG_Reset; + } + } + else + { + if (status != FLASH_TIMEOUT) + { + FLASH->CTLR &= CR_OPTPG_Reset; + } + } + } + return status; +} + +/******************************************************************************** +* Function Name : FLASH_ProgramWord +* Description : Programs a word at a specified address. +* Input : Address: specifies the address to be programmed. +* Data: specifies the data to be programmed. +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + __IO uint32_t tmp = 0; + + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + FLASH->CTLR |= CR_PG_Set; + + *(__IO uint16_t*)Address = (uint16_t)Data; + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + tmp = Address + 2; + *(__IO uint16_t*) tmp = Data >> 16; + status = FLASH_WaitForLastOperation(ProgramTimeout); + FLASH->CTLR &= CR_PG_Reset; + } + else + { + FLASH->CTLR &= CR_PG_Reset; + } + } + + return status; +} + +/******************************************************************************** +* Function Name : FLASH_ProgramHalfWord +* Description : Programs a half word at a specified address. +* Input : Address: specifies the address to be programmed. +* Data: specifies the data to be programmed. +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + FLASH->CTLR |= CR_PG_Set; + *(__IO uint16_t*)Address = Data; + status = FLASH_WaitForLastOperation(ProgramTimeout); + FLASH->CTLR &= CR_PG_Reset; + } + + return status; +} + +/******************************************************************************** +* Function Name : FLASH_ProgramOptionByteData +* Description : Programs a half word at a specified Option Byte Data address. +* Input : Address: specifies the address to be programmed. +* Data: specifies the data to be programmed. +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data) +{ + FLASH_Status status = FLASH_COMPLETE; + status = FLASH_WaitForLastOperation(ProgramTimeout); + if(status == FLASH_COMPLETE) + { + FLASH->OBKEYR = FLASH_KEY1; + FLASH->OBKEYR = FLASH_KEY2; + FLASH->CTLR |= CR_OPTPG_Set; + *(__IO uint16_t*)Address = Data; + status = FLASH_WaitForLastOperation(ProgramTimeout); + if(status != FLASH_TIMEOUT) + { + FLASH->CTLR &= CR_OPTPG_Reset; + } + } + + return status; +} + +/******************************************************************************** +* Function Name : FLASH_EnableWriteProtection +* Description : Write protects the desired pages +* Input : FLASH_Pages: specifies the address of the pages to be write protected. +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages) +{ + uint16_t WRP0_Data = 0xFFFF, WRP1_Data = 0xFFFF, WRP2_Data = 0xFFFF, WRP3_Data = 0xFFFF; + + FLASH_Status status = FLASH_COMPLETE; + + FLASH_Pages = (uint32_t)(~FLASH_Pages); + WRP0_Data = (uint16_t)(FLASH_Pages & WRP0_Mask); + WRP1_Data = (uint16_t)((FLASH_Pages & WRP1_Mask) >> 8); + WRP2_Data = (uint16_t)((FLASH_Pages & WRP2_Mask) >> 16); + WRP3_Data = (uint16_t)((FLASH_Pages & WRP3_Mask) >> 24); + + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + FLASH->OBKEYR = FLASH_KEY1; + FLASH->OBKEYR = FLASH_KEY2; + FLASH->CTLR |= CR_OPTPG_Set; + if(WRP0_Data != 0xFF) + { + OB->WRPR0 = WRP0_Data; + status = FLASH_WaitForLastOperation(ProgramTimeout); + } + if((status == FLASH_COMPLETE) && (WRP1_Data != 0xFF)) + { + OB->WRPR1 = WRP1_Data; + status = FLASH_WaitForLastOperation(ProgramTimeout); + } + if((status == FLASH_COMPLETE) && (WRP2_Data != 0xFF)) + { + OB->WRPR2 = WRP2_Data; + status = FLASH_WaitForLastOperation(ProgramTimeout); + } + + if((status == FLASH_COMPLETE)&& (WRP3_Data != 0xFF)) + { + OB->WRPR3 = WRP3_Data; + status = FLASH_WaitForLastOperation(ProgramTimeout); + } + + if(status != FLASH_TIMEOUT) + { + FLASH->CTLR &= CR_OPTPG_Reset; + } + } + return status; +} + +/******************************************************************************** +* Function Name : FLASH_ReadOutProtection +* Description : Enables or disables the read out protection. +* Input : Newstate: new state of the ReadOut Protection(ENABLE or DISABLE). +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState) +{ + FLASH_Status status = FLASH_COMPLETE; + status = FLASH_WaitForLastOperation(EraseTimeout); + if(status == FLASH_COMPLETE) + { + FLASH->OBKEYR = FLASH_KEY1; + FLASH->OBKEYR = FLASH_KEY2; + FLASH->CTLR |= CR_OPTER_Set; + FLASH->CTLR |= CR_STRT_Set; + status = FLASH_WaitForLastOperation(EraseTimeout); + if(status == FLASH_COMPLETE) + { + FLASH->CTLR &= CR_OPTER_Reset; + FLASH->CTLR |= CR_OPTPG_Set; + if(NewState != DISABLE) + { + OB->RDPR = 0x00; + } + else + { + OB->RDPR = RDP_Key; + } + status = FLASH_WaitForLastOperation(EraseTimeout); + + if(status != FLASH_TIMEOUT) + { + FLASH->CTLR &= CR_OPTPG_Reset; + } + } + else + { + if(status != FLASH_TIMEOUT) + { + FLASH->CTLR &= CR_OPTER_Reset; + } + } + } + return status; +} + +/******************************************************************************** +* Function Name : FLASH_UserOptionByteConfig +* Description : Programs the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY. +* Input : OB_IWDG: Selects the IWDG mode +* OB_IWDG_SW: Software IWDG selected +* OB_IWDG_HW: Hardware IWDG selected +* OB_STOP: Reset event when entering STOP mode. +* OB_STOP_NoRST: No reset generated when entering in STOP +* OB_STOP_RST: Reset generated when entering in STOP +* OB_STDBY: Reset event when entering Standby mode. +* OB_STDBY_NoRST: No reset generated when entering in STANDBY +* OB_STDBY_RST: Reset generated when entering in STANDBY +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY) +{ + FLASH_Status status = FLASH_COMPLETE; + + FLASH->OBKEYR = FLASH_KEY1; + FLASH->OBKEYR = FLASH_KEY2; + status = FLASH_WaitForLastOperation(ProgramTimeout); + + if(status == FLASH_COMPLETE) + { + FLASH->CTLR |= CR_OPTPG_Set; + + OB->USER = OB_IWDG | (uint16_t)(OB_STOP | (uint16_t)(OB_STDBY | ((uint16_t)0xF8))); + + status = FLASH_WaitForLastOperation(ProgramTimeout); + if(status != FLASH_TIMEOUT) + { + FLASH->CTLR &= CR_OPTPG_Reset; + } + } + return status; +} + +/******************************************************************************** +* Function Name : FLASH_GetUserOptionByte +* Description : Returns the FLASH User Option Bytes values. +* Input : None +* Return : The FLASH User Option Bytes values:IWDG_SW(Bit0), RST_STOP(Bit1) +* and RST_STDBY(Bit2). +*********************************************************************************/ +uint32_t FLASH_GetUserOptionByte(void) +{ + return (uint32_t)(FLASH->OBR >> 2); +} + + +/******************************************************************************** +* Function Name : FLASH_GetWriteProtectionOptionByte +* Description : Returns the FLASH Write Protection Option Bytes Register value. +* Input : None +* Return : The FLASH Write Protection Option Bytes Register value +*********************************************************************************/ +uint32_t FLASH_GetWriteProtectionOptionByte(void) +{ + return (uint32_t)(FLASH->WPR); +} + + +/******************************************************************************** +* Function Name : FLASH_GetReadOutProtectionStatus +* Description : Checks whether the FLASH Read Out Protection Status is set or not. +* Input : None +* Return : FLASH ReadOut Protection Status(SET or RESET) +*********************************************************************************/ +FlagStatus FLASH_GetReadOutProtectionStatus(void) +{ + FlagStatus readoutstatus = RESET; + if ((FLASH->OBR & RDPRT_Mask) != (uint32_t)RESET) + { + readoutstatus = SET; + } + else + { + readoutstatus = RESET; + } + return readoutstatus; +} + +/******************************************************************************** +* Function Name : FLASH_GetPrefetchBufferStatus +* Description : Checks whether the FLASH Prefetch Buffer status is set or not. +* Input : None +* Return : FLASH Prefetch Buffer Status (SET or RESET). +*********************************************************************************/ +FlagStatus FLASH_GetPrefetchBufferStatus(void) +{ + FlagStatus bitstatus = RESET; + + if ((FLASH->ACTLR & ACR_PRFTBS_Mask) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************** +* Function Name : FLASH_ITConfig +* Description : Enables or disables the specified FLASH interrupts. +* Input : FLASH_IT: specifies the FLASH interrupt sources to be enabled or disabled. +* FLASH_IT_ERROR: FLASH Error Interrupt +* FLASH_IT_EOP: FLASH end of operation Interrupt +* NewState: new state of the specified Flash interrupts(ENABLE or DISABLE). +* Return : FLASH Prefetch Buffer Status (SET or RESET). +*********************************************************************************/ +void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState) +{ + if(NewState != DISABLE) + { + FLASH->CTLR |= FLASH_IT; + } + else + { + FLASH->CTLR &= ~(uint32_t)FLASH_IT; + } +} + + +/******************************************************************************** +* Function Name : FLASH_GetFlagStatus +* Description : Checks whether the specified FLASH flag is set or not. +* Input : FLASH_FLAG: specifies the FLASH flag to check. +* FLASH_FLAG_BSY: FLASH Busy flag +* FLASH_FLAG_PGERR: FLASH Program error flag +* FLASH_FLAG_WRPRTERR: FLASH Write protected error flag +* FLASH_FLAG_EOP: FLASH End of Operation flag +* FLASH_FLAG_OPTERR: FLASH Option Byte error flag +* Return : The new state of FLASH_FLAG (SET or RESET). +*********************************************************************************/ +FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG) +{ + FlagStatus bitstatus = RESET; + + if(FLASH_FLAG == FLASH_FLAG_OPTERR) + { + if((FLASH->OBR & FLASH_FLAG_OPTERR) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + else + { + if((FLASH->STATR & FLASH_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + } + return bitstatus; +} + +/******************************************************************************** +* Function Name : FLASH_ClearFlag +* Description : Clears the FLASH's pending flags. +* Input : FLASH_FLAG: specifies the FLASH flags to clear. +* FLASH_FLAG_PGERR: FLASH Program error flag +* FLASH_FLAG_WRPRTERR: FLASH Write protected error flag +* FLASH_FLAG_EOP: FLASH End of Operation flag +* Return : None +*********************************************************************************/ +void FLASH_ClearFlag(uint32_t FLASH_FLAG) +{ + + FLASH->STATR = FLASH_FLAG; + +} + +/******************************************************************************** +* Function Name : FLASH_GetStatus +* Description : Returns the FLASH Status. +* Input : None +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP or FLASH_COMPLETE. +*********************************************************************************/ +FLASH_Status FLASH_GetStatus(void) +{ + FLASH_Status flashstatus = FLASH_COMPLETE; + + if((FLASH->STATR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY) + { + flashstatus = FLASH_BUSY; + } + else + { + if((FLASH->STATR & FLASH_FLAG_PGERR) != 0) + { + flashstatus = FLASH_ERROR_PG; + } + else + { + if((FLASH->STATR & FLASH_FLAG_WRPRTERR) != 0 ) + { + flashstatus = FLASH_ERROR_WRP; + } + else + { + flashstatus = FLASH_COMPLETE; + } + } + } + return flashstatus; +} + +/******************************************************************************** +* Function Name : FLASH_GetBank1Status +* Description : Returns the FLASH Bank1 Status. +* Input : None +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP or FLASH_COMPLETE. +*********************************************************************************/ +FLASH_Status FLASH_GetBank1Status(void) +{ + FLASH_Status flashstatus = FLASH_COMPLETE; + + if((FLASH->STATR & FLASH_FLAG_BANK1_BSY) == FLASH_FLAG_BSY) + { + flashstatus = FLASH_BUSY; + } + else + { + if((FLASH->STATR & FLASH_FLAG_BANK1_PGERR) != 0) + { + flashstatus = FLASH_ERROR_PG; + } + else + { + if((FLASH->STATR & FLASH_FLAG_BANK1_WRPRTERR) != 0 ) + { + flashstatus = FLASH_ERROR_WRP; + } + else + { + flashstatus = FLASH_COMPLETE; + } + } + } + return flashstatus; +} + + +/******************************************************************************** +* Function Name : FLASH_WaitForLastOperation +* Description : Waits for a Flash operation to complete or a TIMEOUT to occur. +* Input : Timeout: FLASH programming Timeout +* Return : FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, +* FLASH_ERROR_WRP or FLASH_COMPLETE. +*********************************************************************************/ +FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) +{ + FLASH_Status status = FLASH_COMPLETE; + + status = FLASH_GetBank1Status(); + while((status == FLASH_BUSY) && (Timeout != 0x00)) + { + status = FLASH_GetBank1Status(); + Timeout--; + } + if(Timeout == 0x00 ) + { + status = FLASH_TIMEOUT; + } + return status; +} + + +/******************************************************************************** +* Function Name : FLASH_WaitForLastBank1Operation +* Description : Waits for a Flash operation on Bank1 to complete or a TIMEOUT to occur. +* Input : Timeout: FLASH programming Timeout +* Return : FLASH Status: The returned value can be: FLASH_ERROR_PG, +* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. +*********************************************************************************/ +FLASH_Status FLASH_WaitForLastBank1Operation(uint32_t Timeout) +{ + FLASH_Status status = FLASH_COMPLETE; + + status = FLASH_GetBank1Status(); + while((status == FLASH_FLAG_BANK1_BSY) && (Timeout != 0x00)) + { + status = FLASH_GetBank1Status(); + Timeout--; + } + if(Timeout == 0x00 ) + { + status = FLASH_TIMEOUT; + } + return status; +} + +/******************************************************************************** +* Function Name : FLASH_Unlock_Fast +* Description : Unlocks the Fast Program Erase Mode. +* Input : None +* Return : None +*********************************************************************************/ +void FLASH_Unlock_Fast(void) +{ + /* Authorize the FPEC of Bank1 Access */ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + + /* Fast program mode unlock */ + FLASH->MODEKEYR = FLASH_KEY1; + FLASH->MODEKEYR = FLASH_KEY2; +} + +/******************************************************************************** +* Function Name : FLASH_Lock_Fast +* Description : Locks the Fast Program Erase Mode. +* Input : None +* Return : None +*********************************************************************************/ +void FLASH_Lock_Fast(void) +{ + FLASH->CTLR |= CR_LOCK_Set; +} + +/******************************************************************************** +* Function Name : FLASH_ErasePage_Fast +* Description : Erases a specified FLASH page (1page = 256Byte). +* Input : Page_Address: The page address to be erased. +* Return : None +*********************************************************************************/ +void FLASH_ErasePage_Fast(uint32_t Page_Address) +{ + Page_Address &= 0xFFFFFF00; + + FLASH->CTLR |= CR_PAGE_ER; + FLASH->ADDR = Page_Address; + FLASH->CTLR |= CR_STRT_Set; + while(FLASH->STATR & SR_BSY); + FLASH->CTLR &= ~CR_PAGE_ER; +} + +/******************************************************************************** +* Function Name : FLASH_EraseBlock_32K_Fast +* Description : Erases a specified FLASH Block (1Block = 32KByte). +* Input : Block_Address: The block address to be erased. +* Return : None +*********************************************************************************/ +void FLASH_EraseBlock_32K_Fast(uint32_t Block_Address) +{ + Block_Address &= 0xFFFF8000; + + FLASH->CTLR |= CR_BER32; + FLASH->ADDR = Block_Address; + FLASH->CTLR |= CR_STRT_Set; + while(FLASH->STATR & SR_BSY); + FLASH->CTLR &= ~CR_BER32; +} + +/******************************************************************************** +* Function Name : FLASH_EraseBlock_64K_Fast +* Description : Erases a specified FLASH Block (1Block = 64KByte). +* Input : Block_Address: The block address to be erased. +* Return : None +*********************************************************************************/ +void FLASH_EraseBlock_64K_Fast(uint32_t Block_Address) +{ + Block_Address &= 0xFFFF0000; + + FLASH->CTLR |= CR_BER64; + FLASH->ADDR = Block_Address; + FLASH->CTLR |= CR_STRT_Set; + while(FLASH->STATR & SR_BSY); + FLASH->CTLR &= ~CR_BER64; +} + +/******************************************************************************** +* Function Name : FLASH_ProgramPage_Fast +* Description : Program a specified FLASH page (1page = 256Byte). +* Input : Page_Address: The page address to be programed. +* Return : None +*********************************************************************************/ +void FLASH_ProgramPage_Fast(uint32_t Page_Address, uint32_t*pbuf) +{ + uint8_t size=64; + + Page_Address &= 0xFFFFFF00; + + FLASH->CTLR |= CR_PAGE_PG; + while(FLASH->STATR & SR_BSY); + while(FLASH->STATR & SR_WR_BSY); + + while(size) + { + *(uint32_t*)Page_Address = *(uint32_t*)pbuf; + Page_Address += 4; + pbuf += 1; + size -= 1; + while (FLASH->STATR & SR_WR_BSY); + } + + FLASH->CTLR |= CR_PG_STRT; + while(FLASH->STATR & SR_BSY); + FLASH->CTLR &= ~CR_PAGE_PG; +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_fsmc.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_fsmc.c new file mode 100644 index 00000000..56e8eb15 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_fsmc.c @@ -0,0 +1,653 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_fsmc.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the FSMC firmware functions. +*******************************************************************************/ +#include "ch32v30x_fsmc.h" +#include "ch32v30x_rcc.h" + + +/* FSMC BCRx Mask */ +#define BCR_MBKEN_Set ((uint32_t)0x00000001) +#define BCR_MBKEN_Reset ((uint32_t)0x000FFFFE) +#define BCR_FACCEN_Set ((uint32_t)0x00000040) + +/* FSMC PCRx Mask */ +#define PCR_PBKEN_Set ((uint32_t)0x00000004) +#define PCR_PBKEN_Reset ((uint32_t)0x000FFFFB) +#define PCR_ECCEN_Set ((uint32_t)0x00000040) +#define PCR_ECCEN_Reset ((uint32_t)0x000FFFBF) +#define PCR_MemoryType_NAND ((uint32_t)0x00000008) + + +/******************************************************************************* +* Function Name : FSMC_NORSRAMDeInit +* Description : Deinitializes the FSMC NOR/SRAM Banks registers to their default +* reset values. +* Input : FSMC_Bank: +* FSMC_Bank1_NORSRAM1: FSMC Bank1 NOR/SRAM1. +* FSMC_Bank1_NORSRAM2: FSMC Bank1 NOR/SRAM2. +* FSMC_Bank1_NORSRAM3: FSMC Bank1 NOR/SRAM3. +* FSMC_Bank1_NORSRAM4: FSMC Bank1 NOR/SRAM4 +* Return : None +*******************************************************************************/ +void FSMC_NORSRAMDeInit(uint32_t FSMC_Bank) +{ + if(FSMC_Bank == FSMC_Bank1_NORSRAM1) + { + FSMC_Bank1->BTCR[FSMC_Bank] = 0x000030DB; + } + else + { + FSMC_Bank1->BTCR[FSMC_Bank] = 0x000030D2; + } + FSMC_Bank1->BTCR[FSMC_Bank + 1] = 0x0FFFFFFF; + FSMC_Bank1E->BWTR[FSMC_Bank] = 0x0FFFFFFF; +} + +/******************************************************************************* +* Function Name : FSMC_NANDDeInit +* Description : Deinitializes the FSMC NAND Banks registers to their default +* reset values. +* Input : FSMC_Bank: +* FSMC_Bank2_NAND: FSMC Bank2 NAND. +* FSMC_Bank3_NAND: FSMC Bank3 NAND. +* Return : None +*******************************************************************************/ +void FSMC_NANDDeInit(uint32_t FSMC_Bank) +{ + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->PCR2 = 0x00000018; + FSMC_Bank2->SR2 = 0x00000040; + FSMC_Bank2->PMEM2 = 0xFCFCFCFC; + FSMC_Bank2->PATT2 = 0xFCFCFCFC; + } + else + { + FSMC_Bank3->PCR3 = 0x00000018; + FSMC_Bank3->SR3 = 0x00000040; + FSMC_Bank3->PMEM3 = 0xFCFCFCFC; + FSMC_Bank3->PATT3 = 0xFCFCFCFC; + } +} + +/******************************************************************************* +* Function Name : FSMC_PCCARDDeInit +* Description : Deinitializes the FSMC PCCARD Bank registers to their default +* reset values. +* Input : None +* Return : None +*******************************************************************************/ +void FSMC_PCCARDDeInit(void) +{ + FSMC_Bank4->PCR4 = 0x00000018; + FSMC_Bank4->SR4 = 0x00000000; + FSMC_Bank4->PMEM4 = 0xFCFCFCFC; + FSMC_Bank4->PATT4 = 0xFCFCFCFC; + FSMC_Bank4->PIO4 = 0xFCFCFCFC; +} + +/******************************************************************************* +* Function Name : FSMC_NORSRAMInit +* Description : Initializes the FSMC NOR/SRAM Banks according to the specified +* parameters in the FSMC_NORSRAMInitStruct. +* Input : FSMC_NORSRAMInitStruct:pointer to a FSMC_NORSRAMInitTypeDef +* structure that contains the configuration information for the FSMC NOR/SRAM +* specified Banks. +* Return : None +*******************************************************************************/ +void FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct) +{ + FSMC_Bank1->BTCR[FSMC_NORSRAMInitStruct->FSMC_Bank] = + (uint32_t)FSMC_NORSRAMInitStruct->FSMC_DataAddressMux | + FSMC_NORSRAMInitStruct->FSMC_MemoryType | + FSMC_NORSRAMInitStruct->FSMC_MemoryDataWidth | + FSMC_NORSRAMInitStruct->FSMC_BurstAccessMode | + FSMC_NORSRAMInitStruct->FSMC_AsynchronousWait | + FSMC_NORSRAMInitStruct->FSMC_WaitSignalPolarity | + FSMC_NORSRAMInitStruct->FSMC_WrapMode | + FSMC_NORSRAMInitStruct->FSMC_WaitSignalActive | + FSMC_NORSRAMInitStruct->FSMC_WriteOperation | + FSMC_NORSRAMInitStruct->FSMC_WaitSignal | + FSMC_NORSRAMInitStruct->FSMC_ExtendedMode | + FSMC_NORSRAMInitStruct->FSMC_WriteBurst; + + if(FSMC_NORSRAMInitStruct->FSMC_MemoryType == FSMC_MemoryType_NOR) + { + FSMC_Bank1->BTCR[FSMC_NORSRAMInitStruct->FSMC_Bank] |= (uint32_t)BCR_FACCEN_Set; + } + + FSMC_Bank1->BTCR[FSMC_NORSRAMInitStruct->FSMC_Bank+1] = + (uint32_t)FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressSetupTime | + (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressHoldTime << 4) | + (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataSetupTime << 8) | + (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_BusTurnAroundDuration << 16) | + (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_CLKDivision << 20) | + (FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataLatency << 24) | + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AccessMode; + + if(FSMC_NORSRAMInitStruct->FSMC_ExtendedMode == FSMC_ExtendedMode_Enable) + { + FSMC_Bank1E->BWTR[FSMC_NORSRAMInitStruct->FSMC_Bank] = + (uint32_t)FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressSetupTime | + (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressHoldTime << 4 )| + (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataSetupTime << 8) | + (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_CLKDivision << 20) | + (FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataLatency << 24) | + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AccessMode; + } + else + { + FSMC_Bank1E->BWTR[FSMC_NORSRAMInitStruct->FSMC_Bank] = 0x0FFFFFFF; + } +} + +/******************************************************************************* +* Function Name : FSMC_NANDInit +* Description : Initializes the FSMC NAND Banks according to the specified +* parameters in the FSMC_NANDInitStruct. +* Input : FSMC_NANDInitStruct : pointer to a FSMC_NANDInitTypeDef +* structure that contains the configuration information for the FSMC +* NAND specified Banks. +* Return : None +*******************************************************************************/ +void FSMC_NANDInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct) +{ + uint32_t tmppcr = 0x00000000, tmppmem = 0x00000000, tmppatt = 0x00000000; + + tmppcr = (uint32_t)FSMC_NANDInitStruct->FSMC_Waitfeature | + PCR_MemoryType_NAND | + FSMC_NANDInitStruct->FSMC_MemoryDataWidth | + FSMC_NANDInitStruct->FSMC_ECC | + FSMC_NANDInitStruct->FSMC_ECCPageSize | + (FSMC_NANDInitStruct->FSMC_TCLRSetupTime << 9 )| + (FSMC_NANDInitStruct->FSMC_TARSetupTime << 13); + + tmppmem = (uint32_t)FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime | + (FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime << 8) | + (FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime << 16)| + (FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime << 24); + + tmppatt = (uint32_t)FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime | + (FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime << 8) | + (FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime << 16)| + (FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime << 24); + + if(FSMC_NANDInitStruct->FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->PCR2 = tmppcr; + FSMC_Bank2->PMEM2 = tmppmem; + FSMC_Bank2->PATT2 = tmppatt; + } + else + { + FSMC_Bank3->PCR3 = tmppcr; + FSMC_Bank3->PMEM3 = tmppmem; + FSMC_Bank3->PATT3 = tmppatt; + } +} + +/******************************************************************************* +* Function Name : FSMC_PCCARDInit +* Description : Initializes the FSMC PCCARD Bank according to the specified +* parameters in the FSMC_PCCARDInitStruct. +* Input : FSMC_PCCARDInitStruct : pointer to a FSMC_PCCARDInitTypeDef +* structure that contains the configuration information for the FSMC +* PCCARD Bank. +* Return : None +*******************************************************************************/ +void FSMC_PCCARDInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct) +{ + FSMC_Bank4->PCR4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_Waitfeature | + FSMC_MemoryDataWidth_16b | + (FSMC_PCCARDInitStruct->FSMC_TCLRSetupTime << 9) | + (FSMC_PCCARDInitStruct->FSMC_TARSetupTime << 13); + + FSMC_Bank4->PMEM4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime | + (FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime << 8) | + (FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime << 16)| + (FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime << 24); + + FSMC_Bank4->PATT4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime | + (FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime << 8) | + (FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime << 16)| + (FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime << 24); + + FSMC_Bank4->PIO4 = (uint32_t)FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_SetupTime | + (FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_WaitSetupTime << 8) | + (FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HoldSetupTime << 16)| + (FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HiZSetupTime << 24); +} + +/******************************************************************************* +* Function Name : FSMC_NORSRAMStructInit +* Description : Fills each FSMC_NORSRAMInitStruct member with its default value. +* Input : FSMC_NORSRAMInitStruct: pointer to a FSMC_NORSRAMInitTypeDef +* structure which will be initialized. +* Return : None +*******************************************************************************/ +void FSMC_NORSRAMStructInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct) +{ + FSMC_NORSRAMInitStruct->FSMC_Bank = FSMC_Bank1_NORSRAM1; + FSMC_NORSRAMInitStruct->FSMC_DataAddressMux = FSMC_DataAddressMux_Enable; + FSMC_NORSRAMInitStruct->FSMC_MemoryType = FSMC_MemoryType_SRAM; + FSMC_NORSRAMInitStruct->FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b; + FSMC_NORSRAMInitStruct->FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; + FSMC_NORSRAMInitStruct->FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; + FSMC_NORSRAMInitStruct->FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; + FSMC_NORSRAMInitStruct->FSMC_WrapMode = FSMC_WrapMode_Disable; + FSMC_NORSRAMInitStruct->FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; + FSMC_NORSRAMInitStruct->FSMC_WriteOperation = FSMC_WriteOperation_Enable; + FSMC_NORSRAMInitStruct->FSMC_WaitSignal = FSMC_WaitSignal_Enable; + FSMC_NORSRAMInitStruct->FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; + FSMC_NORSRAMInitStruct->FSMC_WriteBurst = FSMC_WriteBurst_Disable; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressSetupTime = 0xF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AddressHoldTime = 0xF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataSetupTime = 0xFF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_BusTurnAroundDuration = 0xF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_CLKDivision = 0xF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_DataLatency = 0xF; + FSMC_NORSRAMInitStruct->FSMC_ReadWriteTimingStruct->FSMC_AccessMode = FSMC_AccessMode_A; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressSetupTime = 0xF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AddressHoldTime = 0xF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataSetupTime = 0xFF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_BusTurnAroundDuration = 0xF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_CLKDivision = 0xF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_DataLatency = 0xF; + FSMC_NORSRAMInitStruct->FSMC_WriteTimingStruct->FSMC_AccessMode = FSMC_AccessMode_A; +} + +/******************************************************************************* +* Function Name : FSMC_NANDStructInit +* Description : Fills each FSMC_NANDInitStruct member with its default value. +* Input : FSMC_NANDInitStruct: pointer to a FSMC_NANDInitTypeDef +* structure which will be initialized. +* Return : None +*******************************************************************************/ +void FSMC_NANDStructInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct) +{ + FSMC_NANDInitStruct->FSMC_Bank = FSMC_Bank2_NAND; + FSMC_NANDInitStruct->FSMC_Waitfeature = FSMC_Waitfeature_Disable; + FSMC_NANDInitStruct->FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b; + FSMC_NANDInitStruct->FSMC_ECC = FSMC_ECC_Disable; + FSMC_NANDInitStruct->FSMC_ECCPageSize = FSMC_ECCPageSize_256Bytes; + FSMC_NANDInitStruct->FSMC_TCLRSetupTime = 0x0; + FSMC_NANDInitStruct->FSMC_TARSetupTime = 0x0; + FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC; + FSMC_NANDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC; +} + +/******************************************************************************* +* Function Name : FSMC_PCCARDStructInit +* Description : Fills each FSMC_PCCARDInitStruct member with its default value. +* Input : FSMC_PCCARDInitStruct: pointer to a FSMC_PCCARDInitTypeDef +* structure which will be initialized. +* Return : None +*******************************************************************************/ +void FSMC_PCCARDStructInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct) +{ + FSMC_PCCARDInitStruct->FSMC_Waitfeature = FSMC_Waitfeature_Disable; + FSMC_PCCARDInitStruct->FSMC_TCLRSetupTime = 0x0; + FSMC_PCCARDInitStruct->FSMC_TARSetupTime = 0x0; + FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_SetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_CommonSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_SetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_AttributeSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_SetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_WaitSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HoldSetupTime = 0xFC; + FSMC_PCCARDInitStruct->FSMC_IOSpaceTimingStruct->FSMC_HiZSetupTime = 0xFC; +} + +/******************************************************************************* +* Function Name : FSMC_NORSRAMCmd +* Description : Enables or disables the specified NOR/SRAM Memory Bank. +* Input : FSMC_Bank: specifies the FSMC Bank to be used +* FSMC_Bank1_NORSRAM1: FSMC Bank1 NOR/SRAM1 +* FSMC_Bank1_NORSRAM2: FSMC Bank1 NOR/SRAM2 +* FSMC_Bank1_NORSRAM3: FSMC Bank1 NOR/SRAM3 +* FSMC_Bank1_NORSRAM4: FSMC Bank1 NOR/SRAM4 +* NewStateENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void FSMC_NORSRAMCmd(uint32_t FSMC_Bank, FunctionalState NewState) +{ + + if (NewState != DISABLE) + { + FSMC_Bank1->BTCR[FSMC_Bank] |= BCR_MBKEN_Set; + } + else + { + FSMC_Bank1->BTCR[FSMC_Bank] &= BCR_MBKEN_Reset; + } +} + +/******************************************************************************* +* Function Name : FSMC_NANDCmd +* Description : Enables or disables the specified NAND Memory Bank. +* Input : FSMC_Bank: specifies the FSMC Bank to be used +* FSMC_Bank2_NAND: FSMC Bank2 NAND +* FSMC_Bank3_NAND: FSMC Bank3 NAND +* NewStateENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void FSMC_NANDCmd(uint32_t FSMC_Bank, FunctionalState NewState) +{ + + if (NewState != DISABLE) + { + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->PCR2 |= PCR_PBKEN_Set; + } + else + { + FSMC_Bank3->PCR3 |= PCR_PBKEN_Set; + } + } + else + { + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->PCR2 &= PCR_PBKEN_Reset; + } + else + { + FSMC_Bank3->PCR3 &= PCR_PBKEN_Reset; + } + } +} + +/******************************************************************************* +* Function Name : FSMC_PCCARDCmd +* Description : Enables or disables the PCCARD Memory Bank. +* Input : NewStateENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void FSMC_PCCARDCmd(FunctionalState NewState) +{ + + if (NewState != DISABLE) + { + FSMC_Bank4->PCR4 |= PCR_PBKEN_Set; + } + else + { + FSMC_Bank4->PCR4 &= PCR_PBKEN_Reset; + } +} + +/******************************************************************************* +* Function Name : FSMC_NANDECCCmd +* Description : Enables or disables the FSMC NAND ECC feature. +* Input : FSMC_Bank: specifies the FSMC Bank to be used +* FSMC_Bank2_NAND: FSMC Bank2 NAND +* FSMC_Bank3_NAND: FSMC Bank3 NAND +* NewStateENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void FSMC_NANDECCCmd(uint32_t FSMC_Bank, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->PCR2 |= PCR_ECCEN_Set; + } + else + { + FSMC_Bank3->PCR3 |= PCR_ECCEN_Set; + } + } + else + { + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->PCR2 &= PCR_ECCEN_Reset; + } + else + { + FSMC_Bank3->PCR3 &= PCR_ECCEN_Reset; + } + } +} + +/******************************************************************************* +* Function Name : FSMC_GetECC +* Description : Returns the error correction code register value. +* Input : FSMC_Bank: specifies the FSMC Bank to be used +* FSMC_Bank2_NAND: FSMC Bank2 NAND +* FSMC_Bank3_NAND: FSMC Bank3 NAND +* NewStateENABLE or DISABLE. +* Return : eccvalThe Error Correction Code (ECC) value. +*******************************************************************************/ +uint32_t FSMC_GetECC(uint32_t FSMC_Bank) +{ + uint32_t eccval = 0x00000000; + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + eccval = FSMC_Bank2->ECCR2; + } + else + { + eccval = FSMC_Bank3->ECCR3; + } + return(eccval); +} + +/******************************************************************************* +* Function Name : FSMC_ITConfig +* Description : Enables or disables the specified FSMC interrupts. +* Input : FSMC_Bank: specifies the FSMC Bank to be used +* FSMC_Bank2_NAND: FSMC Bank2 NAND +* FSMC_Bank3_NAND: FSMC Bank3 NAND +* FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD +* FSMC_IT: specifies the FSMC interrupt sources to be enabled or disabled. +* FSMC_IT_RisingEdge: Rising edge detection interrupt. +* FSMC_IT_Level: Level edge detection interrupt. +* FSMC_IT_FallingEdge: Falling edge detection interrupt. +* NewStateENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void FSMC_ITConfig(uint32_t FSMC_Bank, uint32_t FSMC_IT, FunctionalState NewState) +{ + + if (NewState != DISABLE) + { + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->SR2 |= FSMC_IT; + } + else if (FSMC_Bank == FSMC_Bank3_NAND) + { + FSMC_Bank3->SR3 |= FSMC_IT; + } + else + { + FSMC_Bank4->SR4 |= FSMC_IT; + } + } + else + { + if(FSMC_Bank == FSMC_Bank2_NAND) + { + + FSMC_Bank2->SR2 &= (uint32_t)~FSMC_IT; + } + else if (FSMC_Bank == FSMC_Bank3_NAND) + { + FSMC_Bank3->SR3 &= (uint32_t)~FSMC_IT; + } + else + { + FSMC_Bank4->SR4 &= (uint32_t)~FSMC_IT; + } + } +} + +/******************************************************************************* +* Function Name : FSMC_GetFlagStatus +* Description : Checks whether the specified FSMC flag is set or not. +* Input : FSMC_Bank: specifies the FSMC Bank to be used +* FSMC_Bank2_NAND: FSMC Bank2 NAND +* FSMC_Bank3_NAND: FSMC Bank3 NAND +* FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD +* FSMC_FLAG: specifies the flag to check. +* FSMC_FLAG_RisingEdge: Rising egde detection Flag. +* FSMC_FLAG_Level: Level detection Flag. +* FSMC_FLAG_FallingEdge: Falling egde detection Flag. +* FSMC_FLAG_FEMPT: Fifo empty Flag. +* NewStateENABLE or DISABLE. +* Return : FlagStatus The new state of FSMC_FLAG (SET or RESET). +*******************************************************************************/ +FlagStatus FSMC_GetFlagStatus(uint32_t FSMC_Bank, uint32_t FSMC_FLAG) +{ + FlagStatus bitstatus = RESET; + uint32_t tmpsr = 0x00000000; + + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + tmpsr = FSMC_Bank2->SR2; + } + else if(FSMC_Bank == FSMC_Bank3_NAND) + { + tmpsr = FSMC_Bank3->SR3; + } + else + { + tmpsr = FSMC_Bank4->SR4; + } + + if ((tmpsr & FSMC_FLAG) != (uint16_t)RESET ) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : FSMC_ClearFlag +* Description : Clears the FSMC's pending flags. +* Input : FSMC_Bank: specifies the FSMC Bank to be used +* FSMC_Bank2_NAND: FSMC Bank2 NAND +* FSMC_Bank3_NAND: FSMC Bank3 NAND +* FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD +* FSMC_FLAG: specifies the flag to check. +* FSMC_FLAG_RisingEdge: Rising egde detection Flag. +* FSMC_FLAG_Level: Level detection Flag. +* FSMC_FLAG_FallingEdge: Falling egde detection Flag. +* Return : None. +*******************************************************************************/ +void FSMC_ClearFlag(uint32_t FSMC_Bank, uint32_t FSMC_FLAG) +{ + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->SR2 &= ~FSMC_FLAG; + } + else if(FSMC_Bank == FSMC_Bank3_NAND) + { + FSMC_Bank3->SR3 &= ~FSMC_FLAG; + } + else + { + FSMC_Bank4->SR4 &= ~FSMC_FLAG; + } +} + +/******************************************************************************* +* Function Name : FSMC_GetITStatus +* Description : Checks whether the specified FSMC interrupt has occurred or not. +* Input : FSMC_Bank: specifies the FSMC Bank to be used +* FSMC_Bank2_NAND: FSMC Bank2 NAND +* FSMC_Bank3_NAND: FSMC Bank3 NAND +* FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD +* FSMC_IT: specifies the FSMC interrupt source to check. +* FSMC_IT_RisingEdge: Rising edge detection interrupt. +* FSMC_IT_Level: Level edge detection interrupt. +* FSMC_IT_FallingEdge: Falling edge detection interrupt. +* Return : ITStatusThe new state of FSMC_IT (SET or RESET). +*******************************************************************************/ +ITStatus FSMC_GetITStatus(uint32_t FSMC_Bank, uint32_t FSMC_IT) +{ + ITStatus bitstatus = RESET; + uint32_t tmpsr = 0x0, itstatus = 0x0, itenable = 0x0; + + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + tmpsr = FSMC_Bank2->SR2; + } + else if(FSMC_Bank == FSMC_Bank3_NAND) + { + tmpsr = FSMC_Bank3->SR3; + } + else + { + tmpsr = FSMC_Bank4->SR4; + } + + itstatus = tmpsr & FSMC_IT; + + itenable = tmpsr & (FSMC_IT >> 3); + if ((itstatus != (uint32_t)RESET) && (itenable != (uint32_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************* +* Function Name : FSMC_ClearITPendingBit +* Description : Clears the FSMC's interrupt pending bits. +* Input : FSMC_Bank: specifies the FSMC Bank to be used +* FSMC_Bank2_NAND: FSMC Bank2 NAND +* FSMC_Bank3_NAND: FSMC Bank3 NAND +* FSMC_Bank4_PCCARD: FSMC Bank4 PCCARD +* FSMC_IT: specifies the FSMC interrupt source to check. +* FSMC_IT_RisingEdge: Rising edge detection interrupt. +* FSMC_IT_Level: Level edge detection interrupt. +* FSMC_IT_FallingEdge: Falling edge detection interrupt. +* Return : None +*******************************************************************************/ +void FSMC_ClearITPendingBit(uint32_t FSMC_Bank, uint32_t FSMC_IT) +{ + + if(FSMC_Bank == FSMC_Bank2_NAND) + { + FSMC_Bank2->SR2 &= ~(FSMC_IT >> 3); + } + else if(FSMC_Bank == FSMC_Bank3_NAND) + { + FSMC_Bank3->SR3 &= ~(FSMC_IT >> 3); + } + else + { + FSMC_Bank4->SR4 &= ~(FSMC_IT >> 3); + } +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_gpio.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_gpio.c new file mode 100644 index 00000000..de9daa7d --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_gpio.c @@ -0,0 +1,490 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_gpio.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the GPIO firmware functions. +*******************************************************************************/ +#include "ch32v30x_gpio.h" +#include "ch32v30x_rcc.h" + +/* MASK */ +#define ECR_PORTPINCONFIG_MASK ((uint16_t)0xFF80) +#define LSB_MASK ((uint16_t)0xFFFF) +#define DBGAFR_POSITION_MASK ((uint32_t)0x000F0000) +#define DBGAFR_SWJCFG_MASK ((uint32_t)0xF0FFFFFF) +#define DBGAFR_LOCATION_MASK ((uint32_t)0x00200000) +#define DBGAFR_NUMBITS_MASK ((uint32_t)0x00100000) + +/******************************************************************************* +* Function Name : GPIO_DeInit +* Description : Deinitializes the GPIOx peripheral registers to their default reset values. +* Input : GPIOx: where x can be (A..G) to select the GPIO peripheral. +* Return : None +*******************************************************************************/ +void GPIO_DeInit(GPIO_TypeDef* GPIOx) +{ + if (GPIOx == GPIOA) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE); + } + else if (GPIOx == GPIOB) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE); + } + else if (GPIOx == GPIOC) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, DISABLE); + } + else if (GPIOx == GPIOD) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, DISABLE); + } + else if (GPIOx == GPIOE) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOE, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOE, DISABLE); + } + else if (GPIOx == GPIOF) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOF, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOF, DISABLE); + } + else + { + if (GPIOx == GPIOG) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOG, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOG, DISABLE); + } + } +} + +/******************************************************************************* +* Function Name : GPIO_AFIODeInit +* Description : Deinitializes the Alternate Functions (remap, event control +* and EXTI configuration) registers to their default reset values. +* Input : None +* Return : None +*******************************************************************************/ +void GPIO_AFIODeInit(void) +{ + RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, DISABLE); +} + +/******************************************************************************* +* Function Name : GPIO_Init +* Description : GPIOx: where x can be (A..G) to select the GPIO peripheral. +* Input : GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that +* contains the configuration information for the specified GPIO peripheral. +* Return : None +*******************************************************************************/ +void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) +{ + uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; + uint32_t tmpreg = 0x00, pinmask = 0x00; + + currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F); + + if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) + { + currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; + } + + if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00) + { + tmpreg = GPIOx->CFGLR; + + for (pinpos = 0x00; pinpos < 0x08; pinpos++) + { + pos = ((uint32_t)0x01) << pinpos; + currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; + + if (currentpin == pos) + { + pos = pinpos << 2; + pinmask = ((uint32_t)0x0F) << pos; + tmpreg &= ~pinmask; + tmpreg |= (currentmode << pos); + + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) + { + GPIOx->BCR = (((uint32_t)0x01) << pinpos); + } + else + { + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) + { + GPIOx->BSHR = (((uint32_t)0x01) << pinpos); + } + } + } + } + GPIOx->CFGLR = tmpreg; + } + + if (GPIO_InitStruct->GPIO_Pin > 0x00FF) + { + tmpreg = GPIOx->CFGHR; + + for (pinpos = 0x00; pinpos < 0x08; pinpos++) + { + pos = (((uint32_t)0x01) << (pinpos + 0x08)); + currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos); + + if (currentpin == pos) + { + pos = pinpos << 2; + pinmask = ((uint32_t)0x0F) << pos; + tmpreg &= ~pinmask; + tmpreg |= (currentmode << pos); + + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) + { + GPIOx->BCR = (((uint32_t)0x01) << (pinpos + 0x08)); + } + + if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) + { + GPIOx->BSHR = (((uint32_t)0x01) << (pinpos + 0x08)); + } + } + } + GPIOx->CFGHR = tmpreg; + } +} + +/******************************************************************************* +* Function Name : GPIO_StructInit +* Description : Fills each GPIO_InitStruct member with its default +* Input : GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure +* which will be initialized. +* Return : None +*******************************************************************************/ +void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct) +{ + GPIO_InitStruct->GPIO_Pin = GPIO_Pin_All; + GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN_FLOATING; +} + +/******************************************************************************* +* Function Name : GPIO_ReadInputDataBit +* Description : GPIOx: where x can be (A..G) to select the GPIO peripheral. +* Input : GPIO_Pin: specifies the port bit to read. +* This parameter can be GPIO_Pin_x where x can be (0..15). +* Return : The input port pin value. +*******************************************************************************/ +uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + uint8_t bitstatus = 0x00; + + if ((GPIOx->INDR & GPIO_Pin) != (uint32_t)Bit_RESET) + { + bitstatus = (uint8_t)Bit_SET; + } + else + { + bitstatus = (uint8_t)Bit_RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : GPIO_ReadInputData +* Description : Reads the specified GPIO input data port. +* Input : GPIOx: where x can be (A..G) to select the GPIO peripheral. +* Return : The output port pin value. +*******************************************************************************/ +uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx) +{ + return ((uint16_t)GPIOx->INDR); +} + +/******************************************************************************* +* Function Name : GPIO_ReadOutputDataBit +* Description : Reads the specified output data port bit. +* Input : GPIOx: where x can be (A..G) to select the GPIO peripheral. +* GPIO_Pin: specifies the port bit to read. +* This parameter can be GPIO_Pin_x where x can be (0..15). +* Return : The output port pin value. +*******************************************************************************/ +uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + uint8_t bitstatus = 0x00; + + if ((GPIOx->OUTDR & GPIO_Pin) != (uint32_t)Bit_RESET) + { + bitstatus = (uint8_t)Bit_SET; + } + else + { + bitstatus = (uint8_t)Bit_RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : GPIO_ReadOutputData +* Description : Reads the specified GPIO output data port. +* Input : GPIOx: where x can be (A..G) to select the GPIO peripheral. +* Return : GPIO output port pin value. +*******************************************************************************/ +uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx) +{ + return ((uint16_t)GPIOx->OUTDR); +} + +/******************************************************************************* +* Function Name : GPIO_SetBits +* Description : Sets the selected data port bits. +* Input : GPIOx: where x can be (A..G) to select the GPIO peripheral. +* GPIO_Pin: specifies the port bits to be written. +* This parameter can be any combination of GPIO_Pin_x where x can be (0..15). +* Return : None +*******************************************************************************/ +void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + GPIOx->BSHR = GPIO_Pin; +} + +/******************************************************************************* +* Function Name : GPIO_ResetBits +* Description : Clears the selected data port bits. +* Input : GPIOx: where x can be (A..G) to select the GPIO peripheral. +* GPIO_Pin: specifies the port bits to be written. +* This parameter can be any combination of GPIO_Pin_x where x can be (0..15). +* Return : None +*******************************************************************************/ +void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + GPIOx->BCR = GPIO_Pin; +} + +/******************************************************************************* +* Function Name : GPIO_WriteBit +* Description : Sets or clears the selected data port bit. +* Input : GPIO_Pin: specifies the port bit to be written. +* This parameter can be one of GPIO_Pin_x where x can be (0..15). +* BitVal: specifies the value to be written to the selected bit. +* Bit_SetL: to clear the port pin. +* Bit_SetH: to set the port pin. +* Return : None +*******************************************************************************/ +void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal) +{ + if (BitVal != Bit_RESET) + { + GPIOx->BSHR = GPIO_Pin; + } + else + { + GPIOx->BCR = GPIO_Pin; + } +} + +/******************************************************************************* +* Function Name : GPIO_Write +* Description : Writes data to the specified GPIO data port. +* Input : GPIOx: where x can be (A..G) to select the GPIO peripheral. +* PortVal: specifies the value to be written to the port output data register. +* Return : None +*******************************************************************************/ +void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal) +{ + GPIOx->OUTDR = PortVal; +} + +/******************************************************************************* +* Function Name : GPIO_PinLockConfig +* Description : Locks GPIO Pins configuration registers. +* Input : GPIOx: where x can be (A..G) to select the GPIO peripheral. +* GPIO_Pin: specifies the port bit to be written. +* This parameter can be any combination of GPIO_Pin_x where x can be (0..15). +* Return : None +*******************************************************************************/ +void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) +{ + uint32_t tmp = 0x00010000; + + tmp |= GPIO_Pin; + GPIOx->LCKR = tmp; + GPIOx->LCKR = GPIO_Pin; + GPIOx->LCKR = tmp; + tmp = GPIOx->LCKR; + tmp = GPIOx->LCKR; +} + +/******************************************************************************* +* Function Name : GPIO_EventOutputConfig +* Description : Selects the GPIO pin used as Event output. +* Input : GPIO_PortSource: selects the GPIO port to be used as source +* for Event output. +* This parameter can be GPIO_PortSourceGPIOx where x can be (A..E). +* GPIO_PinSource: specifies the pin for the Event output. +* This parameter can be GPIO_PinSourcex where x can be (0..15). +* Return : None +*******************************************************************************/ +void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) +{ + uint32_t tmpreg = 0x00; + + tmpreg = AFIO->ECR; + tmpreg &= ECR_PORTPINCONFIG_MASK; + tmpreg |= (uint32_t)GPIO_PortSource << 0x04; + tmpreg |= GPIO_PinSource; + AFIO->ECR = tmpreg; +} + +/******************************************************************************* +* Function Name : GPIO_EventOutputCmd +* Description : Enables or disables the Event Output. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void GPIO_EventOutputCmd(FunctionalState NewState) +{ + if(NewState) + { + AFIO->ECR |= (1<<7); + } + else + { + AFIO->ECR &= ~(1<<7); + } +} + +/******************************************************************************* +* Function Name : GPIO_PinRemapConfig +* Description : Changes the mapping of the specified pin. +* Input : GPIO_Remap: selects the pin to remap. +* GPIO_Remap_SPI1: SPI1 Alternate Function mapping +* GPIO_Remap_I2C1: I2C1 Alternate Function mapping +* GPIO_Remap_USART1: USART1 Alternate Function mapping +* GPIO_Remap_USART2: USART2 Alternate Function mapping +* GPIO_PartialRemap_USART3: USART3 Partial Alternate Function mapping +* GPIO_FullRemap_USART3: USART3 Full Alternate Function mapping +* GPIO_PartialRemap_TIM1: TIM1 Partial Alternate Function mapping +* GPIO_FullRemap_TIM1: TIM1 Full Alternate Function mapping +* GPIO_PartialRemap1_TIM2: TIM2 Partial1 Alternate Function mapping +* GPIO_PartialRemap2_TIM2: TIM2 Partial2 Alternate Function mapping +* GPIO_FullRemap_TIM2: TIM2 Full Alternate Function mapping +* GPIO_PartialRemap_TIM3: TIM3 Partial Alternate Function mapping +* GPIO_FullRemap_TIM3: TIM3 Full Alternate Function mapping +* GPIO_Remap_TIM4: TIM4 Alternate Function mapping +* GPIO_Remap1_CAN1: CAN1 Alternate Function mapping +* GPIO_Remap2_CAN1: CAN1 Alternate Function mapping +* GPIO_Remap_PD01: PD01 Alternate Function mapping +* GPIO_Remap_ADC1_ETRGINJ: ADC1 External Trigger Injected Conversion remapping +* GPIO_Remap_ADC1_ETRGREG: ADC1 External Trigger Regular Conversion remapping +* GPIO_Remap_SWJ_NoJTRST: Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST +* GPIO_Remap_SWJ_JTAGDisable: JTAG-DP Disabled and SW-DP Enabled +* GPIO_Remap_SWJ_Disable: Full SWJ Disabled (JTAG-DP + SW-DP) +* GPIO_Remap_TIM2ITR1_PTP_SOF: Ethernet PTP output or USB OTG SOF (Start of Frame) +* connected to TIM2 Internal Trigger 1 for calibration (only for Connectivity line devices).If the +* is enabled the TIM2 ITR1 is connected to Ethernet PTP output. When Reset TIM2 ITR1 is connected +* to USB OTG SOF output. +* GPIO_Remap_TIM1_DMA: TIM1 DMA requests mapping (only for Value line devices) +* GPIO_Remap_TIM67_DAC_DMA: TIM6/TIM7 and DAC DMA requests remapping (only for High density Value line devices) +* GPIO_Remap_MISC: Miscellaneous Remap (DMA2 Channel5 Position and DAC Trigger remapping, +* only for High density Value line devices) +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState) +{ + uint32_t tmp = 0x00, tmp1 = 0x00, tmpreg = 0x00, tmpmask = 0x00; + + if((GPIO_Remap & 0x80000000) == 0x80000000) + { + tmpreg = AFIO->PCFR2; + } + else + { + tmpreg = AFIO->PCFR1; + } + + tmpmask = (GPIO_Remap & DBGAFR_POSITION_MASK) >> 0x10; + tmp = GPIO_Remap & LSB_MASK; + + if ((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) + { + tmpreg &= DBGAFR_SWJCFG_MASK; + AFIO->PCFR1 &= DBGAFR_SWJCFG_MASK; + } + else if ((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK) + { + tmp1 = ((uint32_t)0x03) << tmpmask; + tmpreg &= ~tmp1; + tmpreg |= ~DBGAFR_SWJCFG_MASK; + } + else + { + tmpreg &= ~(tmp << ((GPIO_Remap >> 0x15)*0x10)); + tmpreg |= ~DBGAFR_SWJCFG_MASK; + } + + if (NewState != DISABLE) + { + tmpreg |= (tmp << ((GPIO_Remap >> 0x15)*0x10)); + } + + if((GPIO_Remap & 0x80000000) == 0x80000000) + { + AFIO->PCFR2 = tmpreg; + } + else + { + AFIO->PCFR1 = tmpreg; + } +} + +/******************************************************************************* +* Function Name : GPIO_EXTILineConfig +* Description : Selects the GPIO pin used as EXTI Line. +* Input : GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines. +* This parameter can be GPIO_PortSourceGPIOx where x can be (A..G). +* GPIO_PinSource: specifies the EXTI line to be configured. +* This parameter can be GPIO_PinSourcex where x can be (0..15). +* Return : None +*******************************************************************************/ +void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) +{ + uint32_t tmp = 0x00; + + tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)); + AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp; + AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03))); +} + + +/******************************************************************************* +* Function Name : GPIO_ETH_MediaInterfaceConfig +* Description : Selects the Ethernet media interface. +* Input : GPIO_ETH_MediaInterface: specifies the Media Interface mode. +* GPIO_ETH_MediaInterface_MII: MII mode +* GPIO_ETH_MediaInterface_RMII: RMII mode +* Return : None +*******************************************************************************/ +void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface) +{ + if(GPIO_ETH_MediaInterface) + { + AFIO->PCFR1 |= (1<<23); + } + else + { + AFIO->PCFR1 &= ~(1<<23); + } +} + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_i2c.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_i2c.c new file mode 100644 index 00000000..88b7fcd3 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_i2c.c @@ -0,0 +1,883 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_i2c.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the I2C firmware functions. +*******************************************************************************/ +#include "ch32v30x_i2c.h" +#include "ch32v30x_rcc.h" + +/* I2C SPE mask */ +#define CTLR1_PE_Set ((uint16_t)0x0001) +#define CTLR1_PE_Reset ((uint16_t)0xFFFE) + +/* I2C START mask */ +#define CTLR1_START_Set ((uint16_t)0x0100) +#define CTLR1_START_Reset ((uint16_t)0xFEFF) + +/* I2C STOP mask */ +#define CTLR1_STOP_Set ((uint16_t)0x0200) +#define CTLR1_STOP_Reset ((uint16_t)0xFDFF) + +/* I2C ACK mask */ +#define CTLR1_ACK_Set ((uint16_t)0x0400) +#define CTLR1_ACK_Reset ((uint16_t)0xFBFF) + +/* I2C ENGC mask */ +#define CTLR1_ENGC_Set ((uint16_t)0x0040) +#define CTLR1_ENGC_Reset ((uint16_t)0xFFBF) + +/* I2C SWRST mask */ +#define CTLR1_SWRST_Set ((uint16_t)0x8000) +#define CTLR1_SWRST_Reset ((uint16_t)0x7FFF) + +/* I2C PEC mask */ +#define CTLR1_PEC_Set ((uint16_t)0x1000) +#define CTLR1_PEC_Reset ((uint16_t)0xEFFF) + +/* I2C ENPEC mask */ +#define CTLR1_ENPEC_Set ((uint16_t)0x0020) +#define CTLR1_ENPEC_Reset ((uint16_t)0xFFDF) + +/* I2C ENARP mask */ +#define CTLR1_ENARP_Set ((uint16_t)0x0010) +#define CTLR1_ENARP_Reset ((uint16_t)0xFFEF) + +/* I2C NOSTRETCH mask */ +#define CTLR1_NOSTRETCH_Set ((uint16_t)0x0080) +#define CTLR1_NOSTRETCH_Reset ((uint16_t)0xFF7F) + +/* I2C registers Masks */ +#define CTLR1_CLEAR_Mask ((uint16_t)0xFBF5) + +/* I2C DMAEN mask */ +#define CTLR2_DMAEN_Set ((uint16_t)0x0800) +#define CTLR2_DMAEN_Reset ((uint16_t)0xF7FF) + +/* I2C LAST mask */ +#define CTLR2_LAST_Set ((uint16_t)0x1000) +#define CTLR2_LAST_Reset ((uint16_t)0xEFFF) + +/* I2C FREQ mask */ +#define CTLR2_FREQ_Reset ((uint16_t)0xFFC0) + +/* I2C ADD0 mask */ +#define OADDR1_ADD0_Set ((uint16_t)0x0001) +#define OADDR1_ADD0_Reset ((uint16_t)0xFFFE) + +/* I2C ENDUAL mask */ +#define OADDR2_ENDUAL_Set ((uint16_t)0x0001) +#define OADDR2_ENDUAL_Reset ((uint16_t)0xFFFE) + +/* I2C ADD2 mask */ +#define OADDR2_ADD2_Reset ((uint16_t)0xFF01) + +/* I2C F/S mask */ +#define CKCFGR_FS_Set ((uint16_t)0x8000) + +/* I2C CCR mask */ +#define CKCFGR_CCR_Set ((uint16_t)0x0FFF) + +/* I2C FLAG mask */ +#define FLAG_Mask ((uint32_t)0x00FFFFFF) + +/* I2C Interrupt Enable mask */ +#define ITEN_Mask ((uint32_t)0x07000000) + +/******************************************************************************* +* Function Name : I2C_DeInit +* Description : Deinitializes the I2Cx peripheral registers to their default +* reset values. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* Return : None +*******************************************************************************/ +void I2C_DeInit(I2C_TypeDef* I2Cx) +{ + if (I2Cx == I2C1) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE); + } + else + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE); + } +} + +/******************************************************************************* +* Function Name : I2C_Init +* Description : Initializes the I2Cx peripheral according to the specified +* parameters in the I2C_InitStruct. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_InitStruct: pointer to a I2C_InitTypeDef structure that +* contains the configuration information for the specified I2C peripheral. +* Return : None +*******************************************************************************/ +void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct) +{ + uint16_t tmpreg = 0, freqrange = 0; + uint16_t result = 0x04; + uint32_t pclk1 = 8000000; + + RCC_ClocksTypeDef rcc_clocks; + + tmpreg = I2Cx->CTLR2; + tmpreg &= CTLR2_FREQ_Reset; + RCC_GetClocksFreq(&rcc_clocks); + pclk1 = rcc_clocks.PCLK1_Frequency; + freqrange = (uint16_t)(pclk1 / 1000000); + tmpreg |= freqrange; + I2Cx->CTLR2 = tmpreg; + + I2Cx->CTLR1 &= CTLR1_PE_Reset; + tmpreg = 0; + + if (I2C_InitStruct->I2C_ClockSpeed <= 100000) + { + result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed << 1)); + + if (result < 0x04) + { + result = 0x04; + } + + tmpreg |= result; + I2Cx->RTR = freqrange + 1; + } + else + { + if (I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_2) + { + result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed * 3)); + } + else + { + result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed * 25)); + result |= I2C_DutyCycle_16_9; + } + + if ((result & CKCFGR_CCR_Set) == 0) + { + result |= (uint16_t)0x0001; + } + + tmpreg |= (uint16_t)(result | CKCFGR_FS_Set); + I2Cx->RTR = (uint16_t)(((freqrange * (uint16_t)300) / (uint16_t)1000) + (uint16_t)1); + } + + I2Cx->CKCFGR = tmpreg; + I2Cx->CTLR1 |= CTLR1_PE_Set; + + + tmpreg = I2Cx->CTLR1; + tmpreg &= CTLR1_CLEAR_Mask; + tmpreg |= (uint16_t)((uint32_t)I2C_InitStruct->I2C_Mode | I2C_InitStruct->I2C_Ack); + I2Cx->CTLR1 = tmpreg; + + I2Cx->OADDR1 = (I2C_InitStruct->I2C_AcknowledgedAddress | I2C_InitStruct->I2C_OwnAddress1); +} + +/******************************************************************************* +* Function Name : I2C_StructInit +* Description : Fills each I2C_InitStruct member with its default value. +* Input : I2C_InitStruct: pointer to an I2C_InitTypeDef structure which +* will be initialized. +* Return : None +*******************************************************************************/ +void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct) +{ + I2C_InitStruct->I2C_ClockSpeed = 5000; + I2C_InitStruct->I2C_Mode = I2C_Mode_I2C; + I2C_InitStruct->I2C_DutyCycle = I2C_DutyCycle_2; + I2C_InitStruct->I2C_OwnAddress1 = 0; + I2C_InitStruct->I2C_Ack = I2C_Ack_Disable; + I2C_InitStruct->I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; +} + +/******************************************************************************* +* Function Name : I2C_Cmd +* Description : Enables or disables the specified I2C peripheral. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR1 |= CTLR1_PE_Set; + } + else + { + I2Cx->CTLR1 &= CTLR1_PE_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_DMACmd +* Description : Enables or disables the specified I2C DMA requests. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR2 |= CTLR2_DMAEN_Set; + } + else + { + I2Cx->CTLR2 &= CTLR2_DMAEN_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_DMALastTransferCmd +* Description : Specifies if the next DMA transfer will be the last one. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR2 |= CTLR2_LAST_Set; + } + else + { + I2Cx->CTLR2 &= CTLR2_LAST_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_GenerateSTART +* Description : Generates I2Cx communication START condition. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR1 |= CTLR1_START_Set; + } + else + { + I2Cx->CTLR1 &= CTLR1_START_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_GenerateSTOP +* Description : Generates I2Cx communication STOP condition. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR1 |= CTLR1_STOP_Set; + } + else + { + I2Cx->CTLR1 &= CTLR1_STOP_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_AcknowledgeConfig +* Description : Enables or disables the specified I2C acknowledge feature. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR1 |= CTLR1_ACK_Set; + } + else + { + I2Cx->CTLR1 &= CTLR1_ACK_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_OwnAddress2Config +* Description : Configures the specified I2C own address2. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* Address: specifies the 7bit I2C own address2. +* Return : None +*******************************************************************************/ +void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address) +{ + uint16_t tmpreg = 0; + + tmpreg = I2Cx->OADDR2; + tmpreg &= OADDR2_ADD2_Reset; + tmpreg |= (uint16_t)((uint16_t)Address & (uint16_t)0x00FE); + I2Cx->OADDR2 = tmpreg; +} + +/******************************************************************************* +* Function Name : I2C_DualAddressCmd +* Description : Enables or disables the specified I2C dual addressing mode. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->OADDR2 |= OADDR2_ENDUAL_Set; + } + else + { + I2Cx->OADDR2 &= OADDR2_ENDUAL_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_GeneralCallCmd +* Description : Enables or disables the specified I2C general call feature. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR1 |= CTLR1_ENGC_Set; + } + else + { + I2Cx->CTLR1 &= CTLR1_ENGC_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_ITConfig +* Description : Enables or disables the specified I2C interrupts. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_IT: specifies the I2C interrupts sources to be enabled or disabled. +* I2C_IT_BUF: Buffer interrupt mask. +* I2C_IT_EVT: Event interrupt mask. +* I2C_IT_ERR: Error interrupt mask. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR2 |= I2C_IT; + } + else + { + I2Cx->CTLR2 &= (uint16_t)~I2C_IT; + } +} + +/******************************************************************************* +* Function Name : I2C_SendData +* Description : Sends a data byte through the I2Cx peripheral. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* Data: Byte to be transmitted. +* Return : None +*******************************************************************************/ +void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data) +{ + I2Cx->DATAR = Data; +} + +/******************************************************************************* +* Function Name : I2C_ReceiveData +* Description : Returns the most recent received data by the I2Cx peripheral. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* Return : The value of the received data. +*******************************************************************************/ +uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx) +{ + return (uint8_t)I2Cx->DATAR; +} + +/******************************************************************************* +* Function Name : I2C_Send7bitAddress +* Description : Transmits the address byte to select the slave device. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* Address: specifies the slave address which will be transmitted. +* I2C_Direction: specifies whether the I2C device will be a +* Transmitter or a Receiver. +* I2C_Direction_Transmitter: Transmitter mode. +* I2C_Direction_Receiver: Receiver mode. +* Return : None +*******************************************************************************/ +void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction) +{ + if (I2C_Direction != I2C_Direction_Transmitter) + { + Address |= OADDR1_ADD0_Set; + } + else + { + Address &= OADDR1_ADD0_Reset; + } + + I2Cx->DATAR = Address; +} + +/******************************************************************************* +* Function Name : I2C_ReadRegister +* Description : Reads the specified I2C register and returns its value. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_Register: specifies the register to read. +* I2C_Register_CTLR1. +* I2C_Register_CTLR2. +* I2C_Register_OADDR1. +* I2C_Register_OADDR2. +* I2C_Register_DATAR. +* I2C_Register_STAR1. +* I2C_Register_STAR2. +* I2C_Register_CKCFGR. +* I2C_Register_RTR. +* Return : The value of the received data. +*******************************************************************************/ +uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register) +{ + __IO uint32_t tmp = 0; + + tmp = (uint32_t) I2Cx; + tmp += I2C_Register; + + return (*(__IO uint16_t *) tmp); +} + +/******************************************************************************* +* Function Name : I2C_SoftwareResetCmd +* Description : Enables or disables the specified I2C software reset. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR1 |= CTLR1_SWRST_Set; + } + else + { + I2Cx->CTLR1 &= CTLR1_SWRST_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_NACKPositionConfig +* Description : Selects the specified I2C NACK position in master receiver mode. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_NACKPosition: specifies the NACK position. +* I2C_NACKPosition_Next: indicates that the next byte will be +* the last received byte. +* I2C_NACKPosition_Current: indicates that current byte is the +* last received byte. +* Return : None +*******************************************************************************/ +void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition) +{ + if (I2C_NACKPosition == I2C_NACKPosition_Next) + { + I2Cx->CTLR1 |= I2C_NACKPosition_Next; + } + else + { + I2Cx->CTLR1 &= I2C_NACKPosition_Current; + } +} + +/******************************************************************************* +* Function Name : I2C_SMBusAlertConfig +* Description : Drives the SMBusAlert pin high or low for the specified I2C. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_SMBusAlert: specifies SMBAlert pin level. +* I2C_SMBusAlert_Low: SMBAlert pin driven low. +* I2C_SMBusAlert_High: SMBAlert pin driven high. +* Return : None +*******************************************************************************/ +void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert) +{ + if (I2C_SMBusAlert == I2C_SMBusAlert_Low) + { + I2Cx->CTLR1 |= I2C_SMBusAlert_Low; + } + else + { + I2Cx->CTLR1 &= I2C_SMBusAlert_High; + } +} + +/******************************************************************************* +* Function Name : I2C_TransmitPEC +* Description : Enables or disables the specified I2C PEC transfer. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR1 |= CTLR1_PEC_Set; + } + else + { + I2Cx->CTLR1 &= CTLR1_PEC_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_PECPositionConfig +* Description : Selects the specified I2C PEC position. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_PECPosition: specifies the PEC position. +* I2C_PECPosition_Next: indicates that the next byte is PEC. +* I2C_PECPosition_Current: indicates that current byte is PEC. +* Return : None +*******************************************************************************/ +void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition) +{ + if (I2C_PECPosition == I2C_PECPosition_Next) + { + I2Cx->CTLR1 |= I2C_PECPosition_Next; + } + else + { + I2Cx->CTLR1 &= I2C_PECPosition_Current; + } +} + +/******************************************************************************* +* Function Name : I2C_CalculatePEC +* Description : Enables or disables the PEC value calculation of the transferred bytes. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR1 |= CTLR1_ENPEC_Set; + } + else + { + I2Cx->CTLR1 &= CTLR1_ENPEC_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_GetPEC +* Description : Returns the PEC value for the specified I2C. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* Return : The PEC value. +*******************************************************************************/ +uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx) +{ + return ((I2Cx->STAR2) >> 8); +} + +/******************************************************************************* +* Function Name : I2C_ARPCmd +* Description : Enables or disables the specified I2C ARP. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : The PEC value. +*******************************************************************************/ +void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + I2Cx->CTLR1 |= CTLR1_ENARP_Set; + } + else + { + I2Cx->CTLR1 &= CTLR1_ENARP_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_StretchClockCmd +* Description : Enables or disables the specified I2C Clock stretching. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState) +{ + if (NewState == DISABLE) + { + I2Cx->CTLR1 |= CTLR1_NOSTRETCH_Set; + } + else + { + I2Cx->CTLR1 &= CTLR1_NOSTRETCH_Reset; + } +} + +/******************************************************************************* +* Function Name : I2C_FastModeDutyCycleConfig +* Description : Selects the specified I2C fast mode duty cycle. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_DutyCycle: specifies the fast mode duty cycle. +* I2C_DutyCycle_2: I2C fast mode Tlow/Thigh = 2. +* I2C_DutyCycle_16_9: I2C fast mode Tlow/Thigh = 16/9. +* Return : None +*******************************************************************************/ +void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle) +{ + if (I2C_DutyCycle != I2C_DutyCycle_16_9) + { + I2Cx->CKCFGR &= I2C_DutyCycle_2; + } + else + { + I2Cx->CKCFGR |= I2C_DutyCycle_16_9; + } +} + + +/******************************************************************************* +* Function Name : I2C_CheckEvent +* Description : Checks whether the last I2Cx Event is equal to the one passed +* as parameter. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_EVENT: specifies the event to be checked. +* I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED : EV1. +* I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED : EV1. +* I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED : EV1. +* I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED : EV1. +* I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED : EV1. +* I2C_EVENT_SLAVE_BYTE_RECEIVED : EV2. +* (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUALF) : EV2. +* (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL) : EV2. +* I2C_EVENT_SLAVE_BYTE_TRANSMITTED : EV3. +* (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUALF) : EV3. +* (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL) : EV3. +* I2C_EVENT_SLAVE_ACK_FAILURE : EV3_2. +* I2C_EVENT_SLAVE_STOP_DETECTED : EV4. +* I2C_EVENT_MASTER_MODE_SELECT : EV5. +* I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED : EV6. +* I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED : EV6. +* I2C_EVENT_MASTER_BYTE_RECEIVED : EV7. +* I2C_EVENT_MASTER_BYTE_TRANSMITTING : EV8. +* I2C_EVENT_MASTER_BYTE_TRANSMITTED : EV8_2. +* I2C_EVENT_MASTER_MODE_ADDRESS10 : EV9. +* Return : ErrorStatus: SUCCESS or ERROR. +*******************************************************************************/ +ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT) +{ + uint32_t lastevent = 0; + uint32_t flag1 = 0, flag2 = 0; + ErrorStatus status = ERROR; + + flag1 = I2Cx->STAR1; + flag2 = I2Cx->STAR2; + flag2 = flag2 << 16; + + lastevent = (flag1 | flag2) & FLAG_Mask; + + if ((lastevent & I2C_EVENT) == I2C_EVENT) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + + return status; +} + + +/******************************************************************************* +* Function Name : I2C_GetLastEvent +* Description : Returns the last I2Cx Event. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* Return : The last event. +*******************************************************************************/ +uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx) +{ + uint32_t lastevent = 0; + uint32_t flag1 = 0, flag2 = 0; + + flag1 = I2Cx->STAR1; + flag2 = I2Cx->STAR2; + flag2 = flag2 << 16; + lastevent = (flag1 | flag2) & FLAG_Mask; + + return lastevent; +} + + +/******************************************************************************* +* Function Name : I2C_GetFlagStatus +* Description : Checks whether the last I2Cx Event is equal to the one passed +* as parameter. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_FLAG: specifies the flag to check. +* I2C_FLAG_DUALF: Dual flag (Slave mode). +* I2C_FLAG_SMBHOST: SMBus host header (Slave mode). +* I2C_FLAG_SMBDEFAULT: SMBus default header (Slave mode). +* I2C_FLAG_GENCALL: General call header flag (Slave mode). +* I2C_FLAG_TRA: Transmitter/Receiver flag. +* I2C_FLAG_BUSY: Bus busy flag. +* I2C_FLAG_MSL: Master/Slave flag. +* I2C_FLAG_SMBALERT: SMBus Alert flag. +* I2C_FLAG_TIMEOUT: Timeout or Tlow error flag. +* I2C_FLAG_PECERR: PEC error in reception flag. +* I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode). +* I2C_FLAG_AF: Acknowledge failure flag. +* I2C_FLAG_ARLO: Arbitration lost flag (Master mode). +* I2C_FLAG_BERR: Bus error flag. +* I2C_FLAG_TXE: Data register empty flag (Transmitter). +* I2C_FLAG_RXNE: Data register not empty (Receiver) flag. +* I2C_FLAG_STOPF: Stop detection flag (Slave mode). +* I2C_FLAG_ADD10: 10-bit header sent flag (Master mode). +* I2C_FLAG_BTF: Byte transfer finished flag. +* I2C_FLAG_ADDR: Address sent flag (Master mode) "ADSL" +* Address matched flag (Slave mode)"ENDA". +* I2C_FLAG_SB: Start bit flag (Master mode). +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG) +{ + FlagStatus bitstatus = RESET; + __IO uint32_t i2creg = 0, i2cxbase = 0; + + i2cxbase = (uint32_t)I2Cx; + i2creg = I2C_FLAG >> 28; + I2C_FLAG &= FLAG_Mask; + + if(i2creg != 0) + { + i2cxbase += 0x14; + } + else + { + I2C_FLAG = (uint32_t)(I2C_FLAG >> 16); + i2cxbase += 0x18; + } + + if(((*(__IO uint32_t *)i2cxbase) & I2C_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : I2C_ClearFlag +* Description : Clears the I2Cx's pending flags. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_FLAG: specifies the flag to clear. +* I2C_FLAG_SMBALERT: SMBus Alert flag. +* I2C_FLAG_TIMEOUT: Timeout or Tlow error flag. +* I2C_FLAG_PECERR: PEC error in reception flag. +* I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode). +* I2C_FLAG_AF: Acknowledge failure flag. +* I2C_FLAG_ARLO: Arbitration lost flag (Master mode). +* I2C_FLAG_BERR: Bus error flag. +* Return : None +*******************************************************************************/ +void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG) +{ + uint32_t flagpos = 0; + + flagpos = I2C_FLAG & FLAG_Mask; + I2Cx->STAR1 = (uint16_t)~flagpos; +} + +/******************************************************************************* +* Function Name : I2C_GetITStatus +* Description : Checks whether the specified I2C interrupt has occurred or not. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* II2C_IT: specifies the interrupt source to check. +* I2C_IT_SMBALERT: SMBus Alert flag. +* I2C_IT_TIMEOUT: Timeout or Tlow error flag. +* I2C_IT_PECERR: PEC error in reception flag. +* I2C_IT_OVR: Overrun/Underrun flag (Slave mode). +* I2C_IT_AF: Acknowledge failure flag. +* I2C_IT_ARLO: Arbitration lost flag (Master mode). +* I2C_IT_BERR: Bus error flag. +* I2C_IT_TXE: Data register empty flag (Transmitter). +* I2C_IT_RXNE: Data register not empty (Receiver) flag. +* I2C_IT_STOPF: Stop detection flag (Slave mode). +* I2C_IT_ADD10: 10-bit header sent flag (Master mode). +* I2C_IT_BTF: Byte transfer finished flag. +* I2C_IT_ADDR: Address sent flag (Master mode) "ADSL" Address matched +* flag (Slave mode)"ENDAD". +* I2C_IT_SB: Start bit flag (Master mode). +* Return : None +*******************************************************************************/ +ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT) +{ + ITStatus bitstatus = RESET; + uint32_t enablestatus = 0; + + enablestatus = (uint32_t)(((I2C_IT & ITEN_Mask) >> 16) & (I2Cx->CTLR2)) ; + I2C_IT &= FLAG_Mask; + + if (((I2Cx->STAR1 & I2C_IT) != (uint32_t)RESET) && enablestatus) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : I2C_ClearITPendingBit +* Description : Clears the I2Cx interrupt pending bits. +* Input : I2Cx: where x can be 1 or 2 to select the I2C peripheral. +* I2C_IT: specifies the interrupt pending bit to clear. +* I2C_IT_SMBALERT: SMBus Alert interrupt. +* I2C_IT_TIMEOUT: Timeout or Tlow error interrupt. +* I2C_IT_PECERR: PEC error in reception interrupt. +* I2C_IT_OVR: Overrun/Underrun interrupt (Slave mode). +* I2C_IT_AF: Acknowledge failure interrupt. +* I2C_IT_ARLO: Arbitration lost interrupt (Master mode). +* I2C_IT_BERR: Bus error interrupt. +* Return : None +*******************************************************************************/ +void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT) +{ + uint32_t flagpos = 0; + + flagpos = I2C_IT & FLAG_Mask; + I2Cx->STAR1 = (uint16_t)~flagpos; +} + + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_iwdg.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_iwdg.c new file mode 100644 index 00000000..51a7ac6b --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_iwdg.c @@ -0,0 +1,109 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_iwdg.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the IWDG firmware functions. +*******************************************************************************/ +#include "ch32v30x_iwdg.h" + +/* CTLR register bit mask */ +#define CTLR_KEY_Reload ((uint16_t)0xAAAA) +#define CTLR_KEY_Enable ((uint16_t)0xCCCC) + +/******************************************************************************* +* Function Name : IWDG_WriteAccessCmd +* Description : Enables or disables write access to IWDG_PSCR and IWDG_RLDR registers. +* Input : WDG_WriteAccess: new state of write access to IWDG_PSCR and +* IWDG_RLDR registers. +* IWDG_WriteAccess_Enable: Enable write access to IWDG_PSCR and +* IWDG_RLDR registers. +* IWDG_WriteAccess_Disable: Disable write access to IWDG_PSCR +* and IWDG_RLDR registers. +* Return : None +*******************************************************************************/ +void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess) +{ + IWDG->CTLR = IWDG_WriteAccess; +} + +/******************************************************************************* +* Function Name : IWDG_SetPrescaler +* Description : Sets IWDG Prescaler value. +* Input : IWDG_Prescaler: specifies the IWDG Prescaler value. +* IWDG_Prescaler_4: IWDG prescaler set to 4. +* IWDG_Prescaler_8: IWDG prescaler set to 8. +* IWDG_Prescaler_16: IWDG prescaler set to 16. +* IWDG_Prescaler_32: IWDG prescaler set to 32. +* IWDG_Prescaler_64: IWDG prescaler set to 64. +* IWDG_Prescaler_128: IWDG prescaler set to 128. +* IWDG_Prescaler_256: IWDG prescaler set to 256. +* Return : None +*******************************************************************************/ +void IWDG_SetPrescaler(uint8_t IWDG_Prescaler) +{ + IWDG->PSCR = IWDG_Prescaler; +} + +/******************************************************************************* +* Function Name : IWDG_SetReload +* Description : Sets IWDG Reload value. +* Input : Reload: specifies the IWDG Reload value. +* This parameter must be a number between 0 and 0x0FFF. +* Return : None +*******************************************************************************/ +void IWDG_SetReload(uint16_t Reload) +{ + IWDG->RLDR = Reload; +} + +/******************************************************************************* +* Function Name : IWDG_ReloadCounter +* Description : Reloads IWDG counter with value defined in the reload register. +* Input : None +* Return : None +*******************************************************************************/ +void IWDG_ReloadCounter(void) +{ + IWDG->CTLR = CTLR_KEY_Reload; +} + +/******************************************************************************* +* Function Name : IWDG_Enable +* Description : Enables IWDG (write access to IWDG_PSCR and IWDG_RLDR registers disabled). +* Input : None +* Return : None +*******************************************************************************/ +void IWDG_Enable(void) +{ + IWDG->CTLR = CTLR_KEY_Enable; +} + +/******************************************************************************* +* Function Name : IWDG_GetFlagStatus +* Description : Checks whether the specified IWDG flag is set or not. +* Input : IWDG_FLAG: specifies the flag to check. +* IWDG_FLAG_PVU: Prescaler Value Update on going. +* IWDG_FLAG_RVU: Reload Value Update on going. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG) +{ + FlagStatus bitstatus = RESET; + + if ((IWDG->STATR & IWDG_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + + + + + diff --git a/demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_misc.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_misc.c similarity index 63% rename from demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_misc.c rename to demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_misc.c index 6d199050..2ed67169 100644 --- a/demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_misc.c +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_misc.c @@ -9,42 +9,35 @@ __IO uint32_t NVIC_Priority_Group = 0; - -/********************************************************************* - * @fn NVIC_PriorityGroupConfig - * - * @brief Configures the priority grouping - pre-emption priority and subpriority. - * - * @param NVIC_PriorityGroup - specifies the priority grouping bits length. - * NVIC_PriorityGroup_0 - 0 bits for pre-emption priority - * 4 bits for subpriority - * NVIC_PriorityGroup_1 - 1 bits for pre-emption priority - * 3 bits for subpriority - * NVIC_PriorityGroup_2 - 2 bits for pre-emption priority - * 2 bits for subpriority - * NVIC_PriorityGroup_3 - 3 bits for pre-emption priority - * 1 bits for subpriority - * NVIC_PriorityGroup_4 - 4 bits for pre-emption priority - * 0 bits for subpriority - * - * @return none - */ +/****************************************************************************************** +* Function Name : NVIC_PriorityGroupConfig +* Description : Configures the priority grouping: pre-emption priority and subpriority. +* Input : NVIC_PriorityGroup: specifies the priority grouping bits length. +* NVIC_PriorityGroup_0: 0 bits for pre-emption priority +* 4 bits for subpriority +* NVIC_PriorityGroup_1: 1 bits for pre-emption priority +* 3 bits for subpriority +* NVIC_PriorityGroup_2: 2 bits for pre-emption priority +* 2 bits for subpriority +* NVIC_PriorityGroup_3: 3 bits for pre-emption priority +* 1 bits for subpriority +* NVIC_PriorityGroup_4: 4 bits for pre-emption priority +* 0 bits for subpriority +* Return : None +*******************************************************************************************/ void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) { NVIC_Priority_Group = NVIC_PriorityGroup; } -/********************************************************************* - * @fn NVIC_Init - * - * @brief Initializes the NVIC peripheral according to the specified parameters in - * the NVIC_InitStruct. - * - * @param NVIC_InitStruct - pointer to a NVIC_InitTypeDef structure that contains the - * configuration information for the specified NVIC peripheral. - * - * @return none - */ +/****************************************************************************************** +* Function Name : NVIC_Init +* Description : Initializes the NVIC peripheral according to the specified parameters in +* the NVIC_InitStruct. +* Input : NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains the +* configuration information for the specified NVIC peripheral. +* Return : None +*******************************************************************************************/ void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) { uint8_t tmppre = 0; diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_opa.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_opa.c new file mode 100644 index 00000000..26884ba1 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_opa.c @@ -0,0 +1,75 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_opa.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the OPA firmware functions. +***************************************************************************************/ +#include "ch32v30x_opa.h" + + +#define OPA_MASK ((uint32_t)0x000F) +#define OPA_Total_NUM 4 +/******************************************************************************** +* Function Name : OPA_DeInit +* Description : Deinitializes the OPA peripheral registers to their default +* reset values. +* Input : None +* Return : None +*********************************************************************************/ +void OPA_DeInit(void) +{ + OPA->CR=0; +} + +/******************************************************************************** +* Function Name : OPA_Init +* Description : Initializes the OPA peripheral according to the specified +* parameters in the OPA_InitStruct. +* Input : OPA_InitStruct: pointer to a OPA_InitTypeDef structure +* Return : None +*********************************************************************************/ +void OPA_Init(OPA_InitTypeDef* OPA_InitStruct) +{ + uint32_t tmp=0; + tmp=OPA->CR; + tmp &=~(OPA_MASK<<(OPA_InitStruct->OPA_NUM*OPA_Total_NUM)); + tmp |= (( (OPA_InitStruct->PSEL<NSEL<Mode<OPA_NUM*OPA_Total_NUM)); + OPA->CR=tmp; +} + +/******************************************************************************** +* Function Name : OPA_StructInit +* Description : Fills each OPA_StructInit member with its reset value. +* Input : OPA_StructInit: pointer to a OPA_InitTypeDef structure +* Return : None +*********************************************************************************/ +void OPA_StructInit(OPA_InitTypeDef* OPA_InitStruct) +{ + OPA_InitStruct->Mode = OUT_IO; + OPA_InitStruct->PSEL = CHP0; + OPA_InitStruct->NSEL = CHN0; + OPA_InitStruct->OPA_NUM = OPA1; +} + +/******************************************************************************** +* Function Name : OPA_Cmd +* Description : Enables or disables the specified OPA peripheral. +* Input : OPA_NUM : Select OPA +* NewState: ENABLE or DISABLE. +* Return : None +*********************************************************************************/ +void OPA_Cmd(OPA_Num_TypeDef OPA_NUM, FunctionalState NewState) +{ + if(NewState==ENABLE) + { + OPA->CR |= (1<<(OPA_NUM*OPA_Total_NUM)); + } + else + { + OPA->CR &= ~(1<<(OPA_NUM*OPA_Total_NUM)); + } +} + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_pwr.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_pwr.c new file mode 100644 index 00000000..3392ebf2 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_pwr.c @@ -0,0 +1,328 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_pwr.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the PWR firmware functions. +********************************************************************************/ +#include "ch32v30x_pwr.h" +#include "ch32v30x_rcc.h" + +/* PWR registers bit mask */ +/* CTLR register bit mask */ +#define CTLR_DS_MASK ((uint32_t)0xFFFFFFFC) +#define CTLR_PLS_MASK ((uint32_t)0xFFFFFF1F) + +/******************************************************************************** +* Function Name : PWR_DeInit +* Description : Deinitializes the PWR peripheral registers to their default +* reset values. +* Input : None +* Return : None +*********************************************************************************/ +void PWR_DeInit(void) +{ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, DISABLE); +} + + +/******************************************************************************** +* Function Name : PWR_BackupAccessCmd +* Description : Enables or disables access to the RTC and backup registers. +* Input : NewState: new state of the access to the RTC and backup registers, +* This parameter can be: ENABLE or DISABLE. +* Return : None +*********************************************************************************/ +void PWR_BackupAccessCmd(FunctionalState NewState) +{ + if(NewState) + { + PWR->CTLR |= (1<<8); + } + else{ + PWR->CTLR &= ~(1<<8); + } +} + + +/******************************************************************************** +* Function Name : PWR_PVDCmd +* Description : Enables or disables the Power Voltage Detector(PVD). +* Input : NewState: new state of the PVD(ENABLE or DISABLE). +* Return : None +*********************************************************************************/ +void PWR_PVDCmd(FunctionalState NewState) +{ + if(NewState) + { + PWR->CTLR |= (1<<4); + } + else{ + PWR->CTLR &= ~(1<<4); + } +} + + +/******************************************************************************** +* Function Name : PWR_PVDLevelConfig +* Description : Configures the voltage threshold detected by the Power Voltage +* Detector(PVD). +* Input : PWR_PVDLevel: specifies the PVD detection level +* PWR_PVDLevel_2V2: PVD detection level set to 2.2V +* PWR_PVDLevel_2V3: PVD detection level set to 2.3V +* PWR_PVDLevel_2V4: PVD detection level set to 2.4V +* PWR_PVDLevel_2V5: PVD detection level set to 2.5V +* PWR_PVDLevel_2V6: PVD detection level set to 2.6V +* PWR_PVDLevel_2V7: PVD detection level set to 2.7V +* PWR_PVDLevel_2V8: PVD detection level set to 2.8V +* PWR_PVDLevel_2V9: PVD detection level set to 2.9V +* Return : None +*********************************************************************************/ +void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel) +{ + uint32_t tmpreg = 0; + tmpreg = PWR->CTLR; + tmpreg &= CTLR_PLS_MASK; + tmpreg |= PWR_PVDLevel; + PWR->CTLR = tmpreg; +} + + +/******************************************************************************** +* Function Name : PWR_WakeUpPinCmd +* Description : Enables or disables the WakeUp Pin functionality. +* Input : NewState: new state of the WakeUp Pin functionality(ENABLE or DISABLE). +* Return : None +*********************************************************************************/ +void PWR_WakeUpPinCmd(FunctionalState NewState) +{ + if(NewState) + { + PWR->CSR |= (1<<8); + } + else{ + PWR->CSR &= ~(1<<8); + } +} + + +/******************************************************************************** +* Function Name : PWR_EnterSTOPMode +* Description : Enters STOP mode. +* Input : PWR_Regulator: specifies the regulator state in STOP mode. +* PWR_Regulator_ON: STOP mode with regulator ON +* PWR_Regulator_LowPower: STOP mode with regulator in low power mode +* PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction. +* PWR_STOPEntry_WFI: enter STOP mode with WFI instruction +* PWR_STOPEntry_WFE: enter STOP mode with WFE instruction +* Return : None +*********************************************************************************/ +void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry) +{ + uint32_t tmpreg = 0; + tmpreg = PWR->CTLR; + tmpreg &= CTLR_DS_MASK; + tmpreg |= PWR_Regulator; + PWR->CTLR = tmpreg; + + NVIC->SCTLR |= (1<<2); + + if(PWR_STOPEntry == PWR_STOPEntry_WFI) + { + __WFI(); + } + else + { + __WFE(); + } + + NVIC->SCTLR &=~ (1<<2); +} + +/******************************************************************************** +* Function Name : PWR_EnterSTANDBYMode +* Description : Enters STANDBY mode. +* Input : None +* Return : None +*********************************************************************************/ +void PWR_EnterSTANDBYMode(void) +{ + PWR->CTLR |= PWR_CTLR_CWUF; + PWR->CTLR |= PWR_CTLR_PDDS; + NVIC->SCTLR |= (1<<2); + + __WFI(); +} + + +/******************************************************************************** +* Function Name : PWR_GetFlagStatus +* Description : Checks whether the specified PWR flag is set or not. +* Input : PWR_FLAG: specifies the flag to check. +* PWR_FLAG_WU: Wake Up flag +* PWR_FLAG_SB: StandBy flag +* PWR_FLAG_PVDO: PVD Output +* Return : The new state of PWR_FLAG (SET or RESET). +*********************************************************************************/ +FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG) +{ + FlagStatus bitstatus = RESET; + + if ((PWR->CSR & PWR_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + + +/******************************************************************************** +* Function Name : PWR_ClearFlag +* Description : Clears the PWR's pending flags. +* Input : PWR_FLAG: specifies the flag to clear. +* PWR_FLAG_WU: Wake Up flag +* PWR_FLAG_SB: StandBy flag +* Return : None +*********************************************************************************/ +void PWR_ClearFlag(uint32_t PWR_FLAG) +{ + PWR->CTLR |= PWR_FLAG << 2; +} + +/******************************************************************************* +* Function Name : PWR_EnterSTOPMode_RAM +* Description : Enters STOP mode with RAM data retention function on. +* Input : PWR_Regulator: specifies the regulator state in STOP mode. +* PWR_Regulator_ON: STOP mode with regulator ON +* PWR_Regulator_LowPower: STOP mode with regulator in low power mode +* PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction. +* PWR_STOPEntry_WFI: enter STOP mode with WFI instruction +* PWR_STOPEntry_WFE: enter STOP mode with WFE instruction +* Return : None +*******************************************************************************/ +void PWR_EnterSTOPMode_RAM(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry) +{ + uint32_t tmpreg = 0; + tmpreg = PWR->CTLR; + tmpreg &= CTLR_DS_MASK; + tmpreg |= PWR_Regulator; + + //2K+30K in standby w power. + tmpreg |= (0x1<<16)|(0x1<<17); + + PWR->CTLR = tmpreg; + + NVIC->SCTLR |= (1<<2); + + if(PWR_STOPEntry == PWR_STOPEntry_WFI) + { + __WFI(); + } + else + { + __WFE(); + } + + NVIC->SCTLR &=~ (1<<2); +} + + +/******************************************************************************* +* Function Name : PWR_EnterSTOPMode_RAM_LV +* Description : Enters STOP mode with RAM data retention function and LV mode on. +* Input : PWR_Regulator: specifies the regulator state in STOP mode. +* PWR_Regulator_ON: STOP mode with regulator ON +* PWR_Regulator_LowPower: STOP mode with regulator in low power mode +* PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction. +* PWR_STOPEntry_WFI: enter STOP mode with WFI instruction +* PWR_STOPEntry_WFE: enter STOP mode with WFE instruction +* Return : None +*******************************************************************************/ +void PWR_EnterSTOPMode_RAM_LV(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry) +{ + uint32_t tmpreg = 0; + tmpreg = PWR->CTLR; + tmpreg &= CTLR_DS_MASK; + tmpreg |= PWR_Regulator; + + //2K+30K in standby w power. + tmpreg |= (0x1<<16)|(0x1<<17); + //LV bit on. + tmpreg |= (0x1<<20); + + PWR->CTLR = tmpreg; + + NVIC->SCTLR |= (1<<2); + + if(PWR_STOPEntry == PWR_STOPEntry_WFI) + { + __WFI(); + } + else + { + __WFE(); + } + + NVIC->SCTLR &=~ (1<<2); +} + + +/******************************************************************************* +* Function Name : PWR_EnterSTANDBYMode_RAM +* Description : Enters STANDBY mode with RAM data retention function on. +* Input : None +* Return : None +*******************************************************************************/ +void PWR_EnterSTANDBYMode_RAM(void) +{ + uint32_t tmpreg = 0; + tmpreg = PWR->CTLR; + + tmpreg |= PWR_CTLR_CWUF; + tmpreg |= PWR_CTLR_PDDS; + + //2K+30K in standby w power. + tmpreg |= (0x1<<16)|(0x1<<17); + + PWR->CTLR = tmpreg; + + NVIC->SCTLR |= (1<<2); + + __WFI(); +} + + +/******************************************************************************* +* Function Name : PWR_EnterSTANDBYMode_RAM_LV +* Description : Enters STANDBY mode with RAM data retention function and LV mode on. +* Input : None +* Return : None +*******************************************************************************/ +void PWR_EnterSTANDBYMode_RAM_LV(void) +{ + uint32_t tmpreg = 0; + tmpreg = PWR->CTLR; + + tmpreg |= PWR_CTLR_CWUF; + tmpreg |= PWR_CTLR_PDDS; + + //2K+30K in standby power. + tmpreg |= (0x1<<16)|(0x1<<17); + //2K+30K in standby LV . + tmpreg |= (0x1<<20); + + PWR->CTLR = tmpreg; + + NVIC->SCTLR |= (1<<2); + + __WFI(); +} + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rcc.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rcc.c new file mode 100644 index 00000000..d855546e --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rcc.c @@ -0,0 +1,1235 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_rcc.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the RCC firmware functions. +*******************************************************************************/ +#include "ch32v30x_rcc.h" + +/* RCC registers bit address in the alias region */ +#define RCC_OFFSET (RCC_BASE - PERIPH_BASE) + +/* BDCTLR Register */ +#define BDCTLR_OFFSET (RCC_OFFSET + 0x20) + +/* RCC registers bit mask */ + +/* CTLR register bit mask */ +#define CTLR_HSEBYP_Reset ((uint32_t)0xFFFBFFFF) +#define CTLR_HSEBYP_Set ((uint32_t)0x00040000) +#define CTLR_HSEON_Reset ((uint32_t)0xFFFEFFFF) +#define CTLR_HSEON_Set ((uint32_t)0x00010000) +#define CTLR_HSITRIM_Mask ((uint32_t)0xFFFFFF07) + +#define CFGR0_PLL_Mask ((uint32_t)0xFFC0FFFF) +#define CFGR0_PLLMull_Mask ((uint32_t)0x003C0000) +#define CFGR0_PLLSRC_Mask ((uint32_t)0x00010000) +#define CFGR0_PLLXTPRE_Mask ((uint32_t)0x00020000) +#define CFGR0_SWS_Mask ((uint32_t)0x0000000C) +#define CFGR0_SW_Mask ((uint32_t)0xFFFFFFFC) +#define CFGR0_HPRE_Reset_Mask ((uint32_t)0xFFFFFF0F) +#define CFGR0_HPRE_Set_Mask ((uint32_t)0x000000F0) +#define CFGR0_PPRE1_Reset_Mask ((uint32_t)0xFFFFF8FF) +#define CFGR0_PPRE1_Set_Mask ((uint32_t)0x00000700) +#define CFGR0_PPRE2_Reset_Mask ((uint32_t)0xFFFFC7FF) +#define CFGR0_PPRE2_Set_Mask ((uint32_t)0x00003800) +#define CFGR0_ADCPRE_Reset_Mask ((uint32_t)0xFFFF3FFF) +#define CFGR0_ADCPRE_Set_Mask ((uint32_t)0x0000C000) + +/* RSTSCKR register bit mask */ +#define RSTSCKR_RMVF_Set ((uint32_t)0x01000000) + +/* CFGR2 register bit mask */ +#define CFGR2_PREDIV1SRC ((uint32_t)0x00010000) +#define CFGR2_PREDIV1 ((uint32_t)0x0000000F) +#define CFGR2_PREDIV2 ((uint32_t)0x000000F0) +#define CFGR2_PLL2MUL ((uint32_t)0x00000F00) +#define CFGR2_PLL3MUL ((uint32_t)0x0000F000) + +/* RCC Flag Mask */ +#define FLAG_Mask ((uint8_t)0x1F) + +/* INTR register byte 2 (Bits[15:8]) base address */ +#define INTR_BYTE2_ADDRESS ((uint32_t)0x40021009) + +/* INTR register byte 3 (Bits[23:16]) base address */ +#define INTR_BYTE3_ADDRESS ((uint32_t)0x4002100A) + +/* CFGR0 register byte 4 (Bits[31:24]) base address */ +#define CFGR0_BYTE4_ADDRESS ((uint32_t)0x40021007) + +/* BDCTLR register base address */ +#define BDCTLR_ADDRESS (PERIPH_BASE + BDCTLR_OFFSET) + + +static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9}; +static __I uint8_t ADCPrescTable[4] = {2, 4, 6, 8}; + +/******************************************************************************* +* Function Name : RCC_DeInit +* Description : Resets the RCC clock configuration to the default reset state. +* Input : None +* Return : None +*******************************************************************************/ +void RCC_DeInit(void) +{ + RCC->CTLR |= (uint32_t)0x00000001; + RCC->CFGR0 &= (uint32_t)0xF8FF0000; + RCC->CTLR &= (uint32_t)0xFEF6FFFF; + RCC->CTLR &= (uint32_t)0xFFFBFFFF; + RCC->CFGR0 &= (uint32_t)0xFF80FFFF; + RCC->INTR = 0x009F0000; +} + +/******************************************************************************* +* Function Name : RCC_HSEConfig +* Description : Configures the External High Speed oscillator (HSE). +* Input : RCC_HSE: +* RCC_HSE_OFF: HSE oscillator OFF. +* RCC_HSE_ON: HSE oscillator ON. +* RCC_HSE_Bypass: HSE oscillator bypassed with external clock. +* Return : None +*******************************************************************************/ +void RCC_HSEConfig(uint32_t RCC_HSE) +{ + RCC->CTLR &= CTLR_HSEON_Reset; + RCC->CTLR &= CTLR_HSEBYP_Reset; + + switch(RCC_HSE) + { + case RCC_HSE_ON: + RCC->CTLR |= CTLR_HSEON_Set; + break; + + case RCC_HSE_Bypass: + RCC->CTLR |= CTLR_HSEBYP_Set | CTLR_HSEON_Set; + break; + + default: + break; + } +} + +/******************************************************************************* +* Function Name : RCC_WaitForHSEStartUp +* Description : Waits for HSE start-up. +* Input : None +* Return : SUCCESS: HSE oscillator is stable and ready to use. +* ERROR: HSE oscillator not yet ready. +*******************************************************************************/ +ErrorStatus RCC_WaitForHSEStartUp(void) +{ + __IO uint32_t StartUpCounter = 0; + + ErrorStatus status = ERROR; + FlagStatus HSEStatus = RESET; + + do + { + HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY); + StartUpCounter++; + } while((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET)); + + if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET) + { + status = SUCCESS; + } + else + { + status = ERROR; + } + + return (status); +} + +/******************************************************************************* +* Function Name : RCC_AdjustHSICalibrationValue +* Description : Adjusts the Internal High Speed oscillator (HSI) calibration value. +* Input : HSICalibrationValue: specifies the calibration trimming value. +* This parameter must be a number between 0 and 0x1F. +* Return : None +*******************************************************************************/ +void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CTLR; + tmpreg &= CTLR_HSITRIM_Mask; + tmpreg |= (uint32_t)HSICalibrationValue << 3; + RCC->CTLR = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_HSICmd +* Description : Enables or disables the Internal High Speed oscillator (HSI). +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_HSICmd(FunctionalState NewState) +{ + if(NewState) + { + RCC->CTLR |= (1<<0); + } + else{ + RCC->CTLR &= ~(1<<0); + } +} + +/******************************************************************************* +* Function Name : RCC_PLLConfig +* Description : Configures the PLL clock source and multiplication factor. +* Input : RCC_PLLSource: specifies the PLL entry clock source. +* RCC_PLLSource_HSI_Div2: HSI oscillator clock divided by 2 +* selected as PLL clock entry. +* RCC_PLLSource_HSE_Div1: HSE oscillator clock selected as PLL +* clock entry. +* RCC_PLLSource_HSE_Div2: HSE oscillator clock divided by 2 +* selected as PLL clock entry. +* RCC_PLLMul: specifies the PLL multiplication factor. +* This parameter can be RCC_PLLMul_x where x:[2,16]. +* For CH32V307: +* RCC_PLLMul_18_EXTEN +* RCC_PLLMul_3_EXTEN +* RCC_PLLMul_4_EXTEN +* RCC_PLLMul_5_EXTEN +* RCC_PLLMul_6_EXTEN +* RCC_PLLMul_7_EXTEN +* RCC_PLLMul_8_EXTEN +* RCC_PLLMul_9_EXTEN +* RCC_PLLMul_10_EXTEN +* RCC_PLLMul_11_EXTEN +* RCC_PLLMul_12_EXTEN +* RCC_PLLMul_13_EXTEN +* RCC_PLLMul_14_EXTEN +* RCC_PLLMul_6_5_EXTEN +* RCC_PLLMul_15_EXTEN +* RCC_PLLMul_16_EXTEN +* For other CH32V30x: +* RCC_PLLMul_2 +* RCC_PLLMul_3 +* RCC_PLLMul_4 +* RCC_PLLMul_5 +* RCC_PLLMul_6 +* RCC_PLLMul_7 +* RCC_PLLMul_8 +* RCC_PLLMul_9 +* RCC_PLLMul_10 +* RCC_PLLMul_11 +* RCC_PLLMul_12 +* RCC_PLLMul_13 +* RCC_PLLMul_14 +* RCC_PLLMul_15 +* RCC_PLLMul_16 +* RCC_PLLMul_18 +* Return : None +*******************************************************************************/ +void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CFGR0; + tmpreg &= CFGR0_PLL_Mask; + tmpreg |= RCC_PLLSource | RCC_PLLMul; + RCC->CFGR0 = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_PLLCmd +* Description : Enables or disables the PLL. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_PLLCmd(FunctionalState NewState) +{ + if(NewState) + { + RCC->CTLR |= (1<<24); + } + else{ + RCC->CTLR &= ~(1<<24); + } +} + +/******************************************************************************* +* Function Name : RCC_SYSCLKConfig +* Description : Configures the system clock (SYSCLK). +* Input : RCC_SYSCLKSource: specifies the clock source used as system clock. +* RCC_SYSCLKSource_HSI: HSI selected as system clock. +* RCC_SYSCLKSource_HSE: HSE selected as system clock. +* RCC_SYSCLKSource_PLLCLK: PLL selected as system clock. +* Return : None +*******************************************************************************/ +void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CFGR0; + tmpreg &= CFGR0_SW_Mask; + tmpreg |= RCC_SYSCLKSource; + RCC->CFGR0 = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_GetSYSCLKSource +* Description : Returns the clock source used as system clock. +* Input : None +* Return : 0x00: HSI used as system clock. +* 0x04: HSE used as system clock. +* 0x08: PLL used as system clock. +*******************************************************************************/ +uint8_t RCC_GetSYSCLKSource(void) +{ + return ((uint8_t)(RCC->CFGR0 & CFGR0_SWS_Mask)); +} + +/******************************************************************************* +* Function Name : RCC_HCLKConfig +* Description : Configures the AHB clock (HCLK). +* Input : RCC_SYSCLK: defines the AHB clock divider. This clock is derived from +* the system clock (SYSCLK). +* RCC_SYSCLK_Div1: AHB clock = SYSCLK. +* RCC_SYSCLK_Div2: AHB clock = SYSCLK/2. +* RCC_SYSCLK_Div4: AHB clock = SYSCLK/4. +* RCC_SYSCLK_Div8: AHB clock = SYSCLK/8. +* RCC_SYSCLK_Div16: AHB clock = SYSCLK/16. +* RCC_SYSCLK_Div64: AHB clock = SYSCLK/64. +* RCC_SYSCLK_Div128: AHB clock = SYSCLK/128. +* RCC_SYSCLK_Div256: AHB clock = SYSCLK/256. +* RCC_SYSCLK_Div512: AHB clock = SYSCLK/512. +* Return : None +*******************************************************************************/ +void RCC_HCLKConfig(uint32_t RCC_SYSCLK) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CFGR0; + tmpreg &= CFGR0_HPRE_Reset_Mask; + tmpreg |= RCC_SYSCLK; + RCC->CFGR0 = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_PCLK1Config +* Description : Configures the Low Speed APB clock (PCLK1). +* Input : RCC_HCLK: defines the APB1 clock divider. This clock is derived from +* the AHB clock (HCLK). +* RCC_HCLK_Div1: APB1 clock = HCLK. +* RCC_HCLK_Div2: APB1 clock = HCLK/2. +* RCC_HCLK_Div4: APB1 clock = HCLK/4. +* RCC_HCLK_Div8: APB1 clock = HCLK/8. +* RCC_HCLK_Div16: APB1 clock = HCLK/16. +* Return : None +*******************************************************************************/ +void RCC_PCLK1Config(uint32_t RCC_HCLK) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CFGR0; + tmpreg &= CFGR0_PPRE1_Reset_Mask; + tmpreg |= RCC_HCLK; + RCC->CFGR0 = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_PCLK2Config +* Description : Configures the High Speed APB clock (PCLK2). +* Input : RCC_HCLK: defines the APB2 clock divider. This clock is derived from +* the AHB clock (HCLK). +* RCC_HCLK_Div1: APB2 clock = HCLK. +* RCC_HCLK_Div2: APB2 clock = HCLK/2. +* RCC_HCLK_Div4: APB2 clock = HCLK/4. +* RCC_HCLK_Div8: APB2 clock = HCLK/8. +* RCC_HCLK_Div16: APB2 clock = HCLK/16. +* Return : None +*******************************************************************************/ +void RCC_PCLK2Config(uint32_t RCC_HCLK) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CFGR0; + tmpreg &= CFGR0_PPRE2_Reset_Mask; + tmpreg |= RCC_HCLK << 3; + RCC->CFGR0 = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_ITConfig +* Description : Enables or disables the specified RCC interrupts. +* Input : RCC_IT: specifies the RCC interrupt sources to be enabled or disabled. +* RCC_IT_LSIRDY: LSI ready interrupt. +* RCC_IT_LSERDY: LSE ready interrupt. +* RCC_IT_HSIRDY: HSI ready interrupt. +* RCC_IT_HSERDY: HSE ready interrupt. +* RCC_IT_PLLRDY: PLL ready interrupt. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + *(__IO uint8_t *) INTR_BYTE2_ADDRESS |= RCC_IT; + } + else + { + *(__IO uint8_t *) INTR_BYTE2_ADDRESS &= (uint8_t)~RCC_IT; + } +} + +/******************************************************************************* +* Function Name : RCC_ADCCLKConfig +* Description : Configures the ADC clock (ADCCLK). +* Input : RCC_PCLK2: defines the ADC clock divider. This clock is derived from +* the APB2 clock (PCLK2). +* RCC_PCLK2_Div2: ADC clock = PCLK2/2. +* RCC_PCLK2_Div4: ADC clock = PCLK2/4. +* RCC_PCLK2_Div6: ADC clock = PCLK2/6. +* RCC_PCLK2_Div8: ADC clock = PCLK2/8. +* Return : None +********************************************************************************/ +void RCC_ADCCLKConfig(uint32_t RCC_PCLK2) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CFGR0; + tmpreg &= CFGR0_ADCPRE_Reset_Mask; + tmpreg |= RCC_PCLK2; + RCC->CFGR0 = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_LSEConfig +* Description : Configures the External Low Speed oscillator (LSE). +* Input : RCC_LSE: specifies the new state of the LSE. +* RCC_LSE_OFF: LSE oscillator OFF. +* RCC_LSE_ON: LSE oscillator ON. +* RCC_LSE_Bypass: LSE oscillator bypassed with external clock. +* Return : None +********************************************************************************/ +void RCC_LSEConfig(uint8_t RCC_LSE) +{ + *(__IO uint8_t *) BDCTLR_ADDRESS = RCC_LSE_OFF; + *(__IO uint8_t *) BDCTLR_ADDRESS = RCC_LSE_OFF; + + switch(RCC_LSE) + { + case RCC_LSE_ON: + *(__IO uint8_t *) BDCTLR_ADDRESS = RCC_LSE_ON; + break; + + case RCC_LSE_Bypass: + *(__IO uint8_t *) BDCTLR_ADDRESS = RCC_LSE_Bypass | RCC_LSE_ON; + break; + + default: + break; + } +} + +/******************************************************************************* +* Function Name : RCC_LSICmd +* Description : Enables or disables the Internal Low Speed oscillator (LSI). +* Input : NewState: ENABLE or DISABLE. +* Return : None +********************************************************************************/ +void RCC_LSICmd(FunctionalState NewState) +{ + if(NewState) + { + RCC->RSTSCKR |= (1<<0); + } + else{ + RCC->RSTSCKR &= ~(1<<0); + } +} + +/******************************************************************************* +* Function Name : RCC_RTCCLKConfig +* Description : Once the RTC clock is selected it can't be changed unless the Backup domain is reset. +* Input : RCC_RTCCLKSource: specifies the RTC clock source. +* RCC_RTCCLKSource_LSE: LSE selected as RTC clock. +* RCC_RTCCLKSource_LSI: LSI selected as RTC clock. +* RCC_RTCCLKSource_HSE_Div128: HSE clock divided by 128 selected as RTC clock. +* Return : None +********************************************************************************/ +void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource) +{ + RCC->BDCTLR |= RCC_RTCCLKSource; +} + +/******************************************************************************* +* Function Name : RCC_RTCCLKCmd +* Description : This function must be used only after the RTC clock was selected +* using the RCC_RTCCLKConfig function. +* Input : NewState: ENABLE or DISABLE. +* Return : None +********************************************************************************/ +void RCC_RTCCLKCmd(FunctionalState NewState) +{ + if(NewState) + { + RCC->BDCTLR |= (1<<15); + } + else{ + RCC->BDCTLR &= ~(1<<15); + } +} + +/******************************************************************************* +* Function Name : RCC_GetClocksFreq +* Description : The result of this function could be not correct when using +* fractional value for HSE crystal. +* Input : RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold +* the clocks frequencies. +* Return : None +********************************************************************************/ +void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks) +{ + uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0, Pll_6_5 = 0; + + tmp = RCC->CFGR0 & CFGR0_SWS_Mask; + + switch (tmp) + { + case 0x00: + RCC_Clocks->SYSCLK_Frequency = HSI_VALUE; + break; + + case 0x04: + RCC_Clocks->SYSCLK_Frequency = HSE_VALUE; + break; + + case 0x08: + pllmull = RCC->CFGR0 & CFGR0_PLLMull_Mask; + pllsource = RCC->CFGR0 & CFGR0_PLLSRC_Mask; + + pllmull = ( pllmull >> 18) + 2; + + if(((*(uint32_t*)0x1FFFF70C) & (1<<14)) != (1<<14)){ /* for other CH32V30x */ + if(pllmull == 17) pllmull = 18; + } + else{ /* for CH32V307 */ + if(pllmull == 2) pllmull = 18; + if(pllmull == 15){ + pllmull = 13; /* *6.5 */ + Pll_6_5 = 1; + } + if(pllmull == 16) pllmull = 15; + if(pllmull == 17) pllmull = 16; + } + + + if (pllsource == 0x00) + { + if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE){ + RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE) * pllmull; + } + else{ + RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >>1) * pllmull; + } + } + else + { + if ((RCC->CFGR0 & CFGR0_PLLXTPRE_Mask) != (uint32_t)RESET) + { + RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE >> 1) * pllmull; + } + else + { + RCC_Clocks->SYSCLK_Frequency = HSE_VALUE * pllmull; + } + } + + if(Pll_6_5 == 1) RCC_Clocks->SYSCLK_Frequency = (RCC_Clocks->SYSCLK_Frequency / 2); + + break; + + default: + RCC_Clocks->SYSCLK_Frequency = HSI_VALUE; + break; + } + + tmp = RCC->CFGR0 & CFGR0_HPRE_Set_Mask; + tmp = tmp >> 4; + presc = APBAHBPrescTable[tmp]; + RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc; + tmp = RCC->CFGR0 & CFGR0_PPRE1_Set_Mask; + tmp = tmp >> 8; + presc = APBAHBPrescTable[tmp]; + RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc; + tmp = RCC->CFGR0 & CFGR0_PPRE2_Set_Mask; + tmp = tmp >> 11; + presc = APBAHBPrescTable[tmp]; + RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc; + tmp = RCC->CFGR0 & CFGR0_ADCPRE_Set_Mask; + tmp = tmp >> 14; + presc = ADCPrescTable[tmp]; + RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc; +} + +/******************************************************************************* +* Function Name : RCC_AHBPeriphClockCmd +* Description : Enables or disables the AHB peripheral clock. +* Input : RCC_AHBPeriph: specifies the AHB peripheral to gates its clock. +* RCC_AHBPeriph_DMA1. +* RCC_AHBPeriph_DMA2. +* RCC_AHBPeriph_SRAM. +* RCC_AHBPeriph_FLITF. +* RCC_AHBPeriph_CRC. +* RCC_AHBPeriph_FSMC +* RCC_AHBPeriph_RNG +* RCC_AHBPeriph_SDIO +* RCC_AHBPeriph_USBHS +* RCC_AHBPeriph_USBOTG +* RCC_AHBPeriph_DVP +* RCC_AHBPeriph_ETH_MAC +* RCC_AHBPeriph_ETH_MAC_Tx +* RCC_AHBPeriph_ETH_MAC_Rx +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RCC->AHBPCENR |= RCC_AHBPeriph; + } + else + { + RCC->AHBPCENR &= ~RCC_AHBPeriph; + } +} + +/******************************************************************************* +* Function Name : RCC_APB2PeriphClockCmd +* Description : Enables or disables the High Speed APB (APB2) peripheral clock. +* Input : RCC_APB2Periph: specifies the APB2 peripheral to gates its clock. +* RCC_APB2Periph_AFIO. +* RCC_APB2Periph_GPIOA. +* RCC_APB2Periph_GPIOB. +* RCC_APB2Periph_GPIOC. +* RCC_APB2Periph_GPIOD. +* RCC_APB2Periph_GPIOE +* RCC_APB2Periph_ADC1. +* RCC_APB2Periph_ADC2 +* RCC_APB2Periph_TIM1. +* RCC_APB2Periph_SPI1. +* RCC_APB2Periph_TIM8 +* RCC_APB2Periph_TIM9 +* RCC_APB2Periph_TIM10 +* RCC_APB2Periph_USART1. +* NewState: ENABLE or DISABLE +* Return : None +*******************************************************************************/ +void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RCC->APB2PCENR |= RCC_APB2Periph; + } + else + { + RCC->APB2PCENR &= ~RCC_APB2Periph; + } +} + +/******************************************************************************* +* Function Name : RCC_APB1PeriphClockCmd +* Description : Enables or disables the Low Speed APB (APB1) peripheral clock. +* Input : RCC_APB1Periph: specifies the APB1 peripheral to gates its clock. +* RCC_APB1Periph_TIM2. +* RCC_APB1Periph_TIM3. +* RCC_APB1Periph_TIM4. +* RCC_APB1Periph_TIM5 +* RCC_APB1Periph_TIM6 +* RCC_APB1Periph_TIM7 +* RCC_APB1Periph_UART6 +* RCC_APB1Periph_UART7 +* RCC_APB1Periph_UART8 +* RCC_APB1Periph_WWDG. +* RCC_APB1Periph_SPI2. +* RCC_APB1Periph_USART2. +* RCC_APB1Periph_USART3. +* RCC_APB1Periph_UART4 +* RCC_APB1Periph_UART5 +* RCC_APB1Periph_I2C1. +* RCC_APB1Periph_I2C2. +* RCC_APB1Periph_USB. +* RCC_APB1Periph_CAN1. +* RCC_APB1Periph_BKP. +* RCC_APB1Periph_PWR. +* RCC_APB1Periph_DAC. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RCC->APB1PCENR |= RCC_APB1Periph; + } + else + { + RCC->APB1PCENR &= ~RCC_APB1Periph; + } +} + +/******************************************************************************* +* Function Name : RCC_APB2PeriphResetCmd +* Description : Forces or releases High Speed APB (APB2) peripheral reset. +* Input : RCC_APB2Periph: specifies the APB2 peripheral to reset. +* RCC_APB2Periph_AFIO. +* RCC_APB2Periph_GPIOA. +* RCC_APB2Periph_GPIOB. +* RCC_APB2Periph_GPIOC. +* RCC_APB2Periph_GPIOD. +* RCC_APB2Periph_GPIOE +* RCC_APB2Periph_ADC1. +* RCC_APB2Periph_ADC2 +* RCC_APB2Periph_TIM1. +* RCC_APB2Periph_SPI1. +* RCC_APB2Periph_TIM8 +* RCC_APB2Periph_TIM9 +* RCC_APB2Periph_TIM10 +* RCC_APB2Periph_USART1. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RCC->APB2PRSTR |= RCC_APB2Periph; + } + else + { + RCC->APB2PRSTR &= ~RCC_APB2Periph; + } +} + +/******************************************************************************* +* Function Name : RCC_APB1PeriphResetCmd +* Description : Forces or releases Low Speed APB (APB1) peripheral reset. +* Input : RCC_APB1Periph: specifies the APB1 peripheral to reset. +* RCC_APB1Periph_TIM2. +* RCC_APB1Periph_TIM3. +* RCC_APB1Periph_TIM4. +* RCC_APB1Periph_TIM5 +* RCC_APB1Periph_TIM6 +* RCC_APB1Periph_TIM7 +* RCC_APB1Periph_UART6 +* RCC_APB1Periph_UART7 +* RCC_APB1Periph_UART8 +* RCC_APB1Periph_WWDG. +* RCC_APB1Periph_SPI2. +* RCC_APB1Periph_USART2. +* RCC_APB1Periph_USART3. +* RCC_APB1Periph_UART4 +* RCC_APB1Periph_UART5 +* RCC_APB1Periph_I2C1. +* RCC_APB1Periph_I2C2. +* RCC_APB1Periph_USB. +* RCC_APB1Periph_CAN1. +* RCC_APB1Periph_BKP. +* RCC_APB1Periph_PWR. +* RCC_APB1Periph_DAC. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RCC->APB1PRSTR |= RCC_APB1Periph; + } + else + { + RCC->APB1PRSTR &= ~RCC_APB1Periph; + } +} + +/******************************************************************************* +* Function Name : RCC_BackupResetCmd +* Description : Forces or releases the Backup domain reset. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_BackupResetCmd(FunctionalState NewState) +{ + if(NewState) + { + RCC->BDCTLR |= (1<<16); + } + else{ + RCC->BDCTLR &= ~(1<<16); + } +} + +/******************************************************************************* +* Function Name : RCC_ClockSecuritySystemCmd +* Description : Enables or disables the Clock Security System. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_ClockSecuritySystemCmd(FunctionalState NewState) +{ + if(NewState) + { + RCC->CTLR |= (1<<19); + } + else{ + RCC->CTLR &= ~(1<<19); + } +} + +/******************************************************************************* +* Function Name : RCC_MCOConfig +* Description : Selects the clock source to output on MCO pin. +* Input : RCC_MCO: specifies the clock source to output. +* RCC_MCO_NoClock: No clock selected. +* RCC_MCO_SYSCLK: System clock selected. +* RCC_MCO_HSI: HSI oscillator clock selected. +* RCC_MCO_HSE: HSE oscillator clock selected. +* RCC_MCO_PLLCLK_Div2: PLL clock divided by 2 selected. +* RCC_MCO_PLL2CLK: PLL2 clock selected +* RCC_MCO_PLL3CLK_Div2: PLL3 clock divided by 2 selected +* RCC_MCO_XT1: External 3-25 MHz oscillator clock selected +* RCC_MCO_PLL3CLK: PLL3 clock selected +* Return : None +*******************************************************************************/ +void RCC_MCOConfig(uint8_t RCC_MCO) +{ + *(__IO uint8_t *) CFGR0_BYTE4_ADDRESS = RCC_MCO; +} + +/******************************************************************************* +* Function Name : RCC_GetFlagStatus +* Description : Checks whether the specified RCC flag is set or not. +* Input : RCC_FLAG: specifies the flag to check. +* RCC_FLAG_HSIRDY: HSI oscillator clock ready. +* RCC_FLAG_HSERDY: HSE oscillator clock ready. +* RCC_FLAG_PLLRDY: PLL clock ready. +* RCC_FLAG_PLL2RDY: PLL2 clock ready. +* RCC_FLAG_PLL3RDY: PLL3 clock ready. +* RCC_FLAG_LSERDY: LSE oscillator clock ready. +* RCC_FLAG_LSIRDY: LSI oscillator clock ready. +* RCC_FLAG_PINRST: Pin reset. +* RCC_FLAG_PORRST: POR/PDR reset. +* RCC_FLAG_SFTRST: Software reset. +* RCC_FLAG_IWDGRST: Independent Watchdog reset. +* RCC_FLAG_WWDGRST: Window Watchdog reset. +* RCC_FLAG_LPWRRST: Low Power reset. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG) +{ + uint32_t tmp = 0; + uint32_t statusreg = 0; + + FlagStatus bitstatus = RESET; + tmp = RCC_FLAG >> 5; + + if (tmp == 1) + { + statusreg = RCC->CTLR; + } + else if (tmp == 2) + { + statusreg = RCC->BDCTLR; + } + else + { + statusreg = RCC->RSTSCKR; + } + + tmp = RCC_FLAG & FLAG_Mask; + + if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : RCC_ClearFlag +* Description : Clears the RCC reset flags. +* Input : None +* Return : None +*******************************************************************************/ +void RCC_ClearFlag(void) +{ + RCC->RSTSCKR |= RSTSCKR_RMVF_Set; +} + +/******************************************************************************* +* Function Name : RCC_GetITStatus +* Description : Checks whether the specified RCC interrupt has occurred or not. +* Input : RCC_IT: specifies the RCC interrupt source to check. +* RCC_IT_LSIRDY: LSI ready interrupt. +* RCC_IT_LSERDY: LSE ready interrupt. +* RCC_IT_HSIRDY: HSI ready interrupt. +* RCC_IT_HSERDY: HSE ready interrupt. +* RCC_IT_PLLRDY: PLL ready interrupt. +* RCC_IT_PLL2RDY: PLL2 ready interrupt. +* RCC_IT_PLL3RDY: PLL3 ready interrupt. +* RCC_IT_CSS: Clock Security System interrupt. +* Return : ITStatus: SET or RESET. +*******************************************************************************/ +ITStatus RCC_GetITStatus(uint8_t RCC_IT) +{ + ITStatus bitstatus = RESET; + + if ((RCC->INTR & RCC_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : RCC_ClearITPendingBit +* Description : Clears the RCC's interrupt pending bits. +* Input : RCC_IT: specifies the interrupt pending bit to clear. +* RCC_IT_LSIRDY: LSI ready interrupt. +* RCC_IT_LSERDY: LSE ready interrupt. +* RCC_IT_HSIRDY: HSI ready interrupt. +* RCC_IT_HSERDY: HSE ready interrupt. +* RCC_IT_PLLRDY: PLL ready interrupt. +* RCC_IT_PLL2RDY: PLL2 ready interrupt. +* RCC_IT_PLL3RDY: PLL3 ready interrupt. +* RCC_IT_CSS: Clock Security System interrupt. +* Return : None +*******************************************************************************/ +void RCC_ClearITPendingBit(uint8_t RCC_IT) +{ + *(__IO uint8_t *) INTR_BYTE3_ADDRESS = RCC_IT; +} + +/******************************************************************************* +* Function Name : RCC_PREDIV1Config +* Description : Configures the PREDIV1 division factor. +* Input : RCC_PREDIV1_Source: specifies the PREDIV1 clock source. +* RCC_PREDIV1_Source_HSE: HSE selected as PREDIV1 clock +* RCC_PREDIV1_Source_PLL2: PLL2 selected as PREDIV1 clock +* RCC_PREDIV1_Div: specifies the PREDIV1 clock division factor. +* This parameter can be RCC_PREDIV1_Divx where x:[1,16] +* Return : None +*******************************************************************************/ +void RCC_PREDIV1Config(uint32_t RCC_PREDIV1_Source, uint32_t RCC_PREDIV1_Div) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CFGR2; + tmpreg &= ~(CFGR2_PREDIV1 | CFGR2_PREDIV1SRC); + tmpreg |= RCC_PREDIV1_Source | RCC_PREDIV1_Div ; + RCC->CFGR2 = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_PREDIV2Config +* Description : Configures the PREDIV2 division factor. +* Input : RCC_PREDIV2_Div: specifies the PREDIV2 clock division factor. +* This parameter can be RCC_PREDIV2_Divx where x:[1,16] +* Return : None +*******************************************************************************/ +void RCC_PREDIV2Config(uint32_t RCC_PREDIV2_Div) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CFGR2; + tmpreg &= ~CFGR2_PREDIV2; + tmpreg |= RCC_PREDIV2_Div; + RCC->CFGR2 = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_PLL2Config +* Description : Configures the PLL2 multiplication factor. +* Input : RCC_PLL2Mul: specifies the PLL2 multiplication factor. +* This parameter can be RCC_PLL2Mul_x where x:{[8,14], 16, 20} +* Return : None +*******************************************************************************/ +void RCC_PLL2Config(uint32_t RCC_PLL2Mul) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CFGR2; + tmpreg &= ~CFGR2_PLL2MUL; + tmpreg |= RCC_PLL2Mul; + RCC->CFGR2 = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_PLL2Cmd +* Description : Enables or disables the PLL2. +* Input : NewState: new state of the PLL2. This parameter can be: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_PLL2Cmd(FunctionalState NewState) +{ + if(NewState) + { + RCC->CTLR |= (1<<26); + } + else{ + RCC->CTLR &= ~(1<<26); + } +} + +/******************************************************************************* +* Function Name : RCC_PLL3Config +* Description : Configures the PLL3 multiplication factor. +* Input : RCC_PLL3Mul: specifies the PLL3 multiplication factor. +* This parameter can be RCC_PLL3Mul_x where x:{[8,14], 16, 20} +* Return : None +*******************************************************************************/ +void RCC_PLL3Config(uint32_t RCC_PLL3Mul) +{ + uint32_t tmpreg = 0; + + tmpreg = RCC->CFGR2; + tmpreg &= ~CFGR2_PLL3MUL; + tmpreg |= RCC_PLL3Mul; + RCC->CFGR2 = tmpreg; +} + +/******************************************************************************* +* Function Name : RCC_PLL3Cmd +* Description : Enables or disables the PLL3. +* Input : NewState: new state of the PLL3. This parameter can be: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_PLL3Cmd(FunctionalState NewState) +{ + if(NewState) + { + RCC->CTLR |= (1<<28); + } + else{ + RCC->CTLR &= ~(1<<28); + } +} + +/******************************************************************************* +* Function Name : RCC_OTGFSCLKConfig +* Description : Configures the USB OTG FS clock (OTGFSCLK). +* Input : RCC_OTGFSCLKSource: specifies the USB OTG FS clock source. +* RCC_OTGFSCLKSource_PLLCLK_Div1: PLL clock divided by 1 selected as USB OTG FS clock source +* RCC_OTGFSCLKSource_PLLCLK_Div2: PLL clock divided by 2 selected as USB OTG FS clock source +* RCC_OTGFSCLKSource_PLLCLK_Div3: PLL clock divided by 3 selected as USB OTG FS clock source +* Return : None +*******************************************************************************/ +void RCC_OTGFSCLKConfig(uint32_t RCC_OTGFSCLKSource) +{ + RCC->CFGR0 &= ~(3<<22); + RCC->CFGR0 |= RCC_OTGFSCLKSource<<22; +} + +/******************************************************************************* +* Function Name : RCC_I2S2CLKConfig +* Description : Configures the I2S2 clock source(I2S2CLK). +* Input : RCC_I2S2CLKSource: specifies the I2S2 clock source. +* RCC_I2S2CLKSource_SYSCLK: system clock selected as I2S2 clock entry +* RCC_I2S2CLKSource_PLL3_VCO: PLL3 VCO clock selected as I2S2 clock entry +* Return : None +*******************************************************************************/ +void RCC_I2S2CLKConfig(uint32_t RCC_I2S2CLKSource) +{ + RCC->CFGR2 &= ~(1<<17); + RCC->CFGR2 |= RCC_I2S2CLKSource<<17; +} + +/******************************************************************************* +* Function Name : RCC_I2S3CLKConfig +* Description : Configures the I2S3 clock source(I2S2CLK). +* Input : RCC_I2S3CLKSource: specifies the I2S3 clock source. +* RCC_I2S3CLKSource_SYSCLK: system clock selected as I2S3 clock entry +* RCC_I2S3CLKSource_PLL3_VCO: PLL3 VCO clock selected as I2S3 clock entry +* Return : None +*******************************************************************************/ +void RCC_I2S3CLKConfig(uint32_t RCC_I2S3CLKSource) +{ + RCC->CFGR2 &= ~(1<<18); + RCC->CFGR2 |= RCC_I2S3CLKSource<<18; +} + +/******************************************************************************* +* Function Name : RCC_AHBPeriphResetCmd +* Description : Forces or releases AHB peripheral reset. +* Input : RCC_AHBPeriph: specifies the AHB peripheral to reset. +* RCC_AHBPeriph_OTG_FS +* RCC_AHBPeriph_ETH_MAC +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_AHBPeriphResetCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RCC->AHBRSTR |= RCC_AHBPeriph; + } + else + { + RCC->AHBRSTR &= ~RCC_AHBPeriph; + } +} + +/******************************************************************************* +* Function Name : RCC_ADCCLKADJcmd +* Description : Enable ADC clock duty cycle adjustment. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_ADCCLKADJcmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RCC->CFGR0 |= (1<<31); + } + else + { + RCC->CFGR0 &= ~(1<<31); + } +} + +/******************************************************************************* +* Function Name : RCC_RNGCLKConfig +* Description : Configures the RNG clock source. +* Input : RCC_RNGCLKSource: specifies the RNG clock source. +* RCC_RNGCLKSource_SYSCLK: system clock selected as RNG clock entry +* RCC_RNGCLKSource_PLL3_VCO: PLL3 VCO clock selected as RNG clock entry +* Return : None +*******************************************************************************/ +void RCC_RNGCLKConfig(uint32_t RCC_RNGCLKSource) +{ + RCC->CFGR2 &= ~(1<<19); + RCC->CFGR2 |= RCC_RNGCLKSource<<19; +} + +/******************************************************************************* +* Function Name : RCC_ETH1GCLKConfig +* Description : Configures the ETH1G clock source. +* Input : RCC_RNGCLKSource: specifies the ETH1G clock source. +* RCC_ETH1GCLKSource_PLL2_VCO: system clock selected as ETH1G clock entry +* RCC_ETH1GCLKSource_PLL3_VCO: PLL3 VCO clock selected as ETH1G clock entry +* RCC_ETH1GCLKSource_PB1_IN GPIO PB1 input clock selected as ETH1G clock entry +* Return : None +*******************************************************************************/ +void RCC_ETH1GCLKConfig(uint32_t RCC_ETH1GCLKSource) +{ + RCC->CFGR2 &= ~(3<<20); + RCC->CFGR2 |= RCC_ETH1GCLKSource<<20; +} + +/******************************************************************************* +* Function Name : RCC_ETH1G_125Mcmd +* Description : Enable ETH1G 125M. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_ETH1G_125Mcmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RCC->CFGR2 |= (1<<22); + } + else + { + RCC->CFGR2 &= ~(1<<22); + } +} + +/******************************************************************************* +* Function Name : RCC_USBHSConfig +* Description : Configures the USBHS clock. +* Input : RCC_USBHS: defines the USBHS clock divider. +* RCC_USBPLL_Div1: USBHS clock = USBPLL. +* RCC_USBPLL_Div2: USBHS clock = USBPLL/2. +* RCC_USBPLL_Div3: USBHS clock = USBPLL/3. +* RCC_USBPLL_Div4: USBHS clock = USBPLL/4. +* RCC_USBPLL_Div5: USBHS clock = USBPLL/5. +* RCC_USBPLL_Div6: USBHS clock = USBPLL/6. +* RCC_USBPLL_Div7: USBHS clock = USBPLL/7. +* RCC_USBPLL_Div8: USBHS clock = USBPLL/8. +* Return : None +*******************************************************************************/ +void RCC_USBHSConfig(uint32_t RCC_USBHS) +{ + RCC->CFGR2 &= ~(7<<24); + RCC->CFGR2 |= RCC_USBHS<<24; +} + +/******************************************************************************* +* Function Name : RCC_USBHSPLLCLKConfig +* Description : Configures the USBHSPLL clock source. +* Input : RCC_RNGCLKSource: specifies the USBHSPLL clock source. +* RCC_HSBHSPLLCLKSource_HSE: HSE clock selected as USBHSPLL clock entry +* RCC_HSBHSPLLCLKSource_HSI: HSI clock selected as USBHSPLL clock entry +* Return : None +*******************************************************************************/ +void RCC_USBHSPLLCLKConfig(uint32_t RCC_USBHSPLLCLKSource) +{ + RCC->CFGR2 &= ~(1<<27); + RCC->CFGR2 |= RCC_USBHSPLLCLKSource<<27; +} + +/******************************************************************************* +* Function Name : RCC_USBHSPLLCKREFCLKConfig +* Description : Configures the USBHSPLL reference clock. +* Input : RCC_USBHSPLLCKREFCLKSource: Select reference clock. +* RCC_USBHSPLLCKREFCLK_3M: reference clock 3Mhz. +* RCC_USBHSPLLCKREFCLK_4M: reference clock 4Mhz. +* RCC_USBHSPLLCKREFCLK_8M: reference clock 8Mhz. +* RCC_USBHSPLLCKREFCLK_5M: reference clock 5Mhz. +* Return : None +*******************************************************************************/ +void RCC_USBHSPLLCKREFCLKConfig(uint32_t RCC_USBHSPLLCKREFCLKSource) +{ + RCC->CFGR2 &= ~(3<<28); + RCC->CFGR2 |= RCC_USBHSPLLCKREFCLKSource<<28; +} + +/******************************************************************************* +* Function Name : RCC_USBHSPHYPLLALIVEcmd +* Description : Enable USBHS PHY control. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RCC_USBHSPHYPLLALIVEcmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RCC->CFGR2 |= (1<<30); + } + else + { + RCC->CFGR2 &= ~(1<<30); + } +} + +/******************************************************************************* +* Function Name : RCC_USBCLK48MConfig +* Description : Configures the USB clock 48MHz source. +* Input : RCC_USBCLK48MSource: specifies the USB clock 48MHz source. +* RCC_USBCLK48MCLKSource_PLLCLK: PLLCLK clock selected as USB clock 48MHz clock entry +* RCC_USBCLK48MCLKSource_USBPHY: USBPHY clock selected as USB clock 48MHz clock entry +* Return : None +*******************************************************************************/ +void RCC_USBCLK48MConfig(uint32_t RCC_USBCLK48MSource) +{ + RCC->CFGR2 &= ~(1<<31); + RCC->CFGR2 |= RCC_USBCLK48MSource<<31; +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rng.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rng.c new file mode 100644 index 00000000..b811df13 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rng.c @@ -0,0 +1,132 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_rng.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the RNG firmware functions. +********************************************************************************/ +#include "ch32v30x_rng.h" +#include "ch32v30x_rcc.h" + +/******************************************************************************* +* Function Name : RNG_Cmd +* Description : Enables or disables the RNG peripheral. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RNG_Cmd(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RNG->CR |= RNG_CR_RNGEN; + } + else + { + RNG->CR &= ~RNG_CR_RNGEN; + } +} + +/******************************************************************************* +* Function Name : RNG_GetRandomNumber +* Description : Returns a 32-bit random number. +* Input : None +* Return : 32-bit random number. +*******************************************************************************/ +uint32_t RNG_GetRandomNumber(void) +{ + return RNG->DR; +} + +/******************************************************************************* +* Function Name : RNG_ITConfig +* Description : Enables or disables the RNG interrupt. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void RNG_ITConfig(FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RNG->CR |= RNG_CR_IE; + } + else + { + RNG->CR &= ~RNG_CR_IE; + } +} + +/******************************************************************************* +* Function Name : RNG_GetFlagStatus +* Description : Checks whether the specified RNG flag is set or not. +* Input : RNG_FLAG: specifies the RNG flag to check. + * RNG_FLAG_DRDY: Data Ready flag. + * RNG_FLAG_CECS: Clock Error Current flag. + * RNG_FLAG_SECS: Seed Error Current flag. +* Return : bitstatusSET or RESET. +*******************************************************************************/ +FlagStatus RNG_GetFlagStatus(uint8_t RNG_FLAG) +{ + FlagStatus bitstatus = RESET; + + if ((RNG->SR & RNG_FLAG) != (uint8_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : RNG_ClearFlag +* Description : Clears the RNG flags. +* Input : RNG_FLAG: specifies the flag to clear. +* RNG_FLAG_CECS: Clock Error Current flag. +* RNG_FLAG_SECS: Seed Error Current flag. +* Return : None +*******************************************************************************/ +void RNG_ClearFlag(uint8_t RNG_FLAG) +{ + RNG->SR = ~(uint32_t)(((uint32_t)RNG_FLAG) << 4); +} + +/******************************************************************************* +* Function Name : RNG_GetFlagStatus +* Description : Checks whether the specified RNG interrupt has occurred or not. +* Input : RNG_IT: specifies the RNG interrupt source to check. +* RNG_IT_CEI: Clock Error Interrupt. +* RNG_IT_SEI: Seed Error Interrupt. +* Return : bitstatusSET or RESET. +*******************************************************************************/ +ITStatus RNG_GetITStatus(uint8_t RNG_IT) +{ + ITStatus bitstatus = RESET; + + if ((RNG->SR & RNG_IT) != (uint8_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : RNG_ClearITPendingBit +* Description : Clears the RNG interrupt pending bit(s). +* Input : RNG_IT: specifies the RNG interrupt pending bit(s) to clear. +* RNG_IT_CEI: Clock Error Interrupt. +* RNG_IT_SEI: Seed Error Interrupt. +* Return : None +*******************************************************************************/ +void RNG_ClearITPendingBit(uint8_t RNG_IT) +{ + RNG->SR = (uint8_t)~RNG_IT; +} + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rtc.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rtc.c new file mode 100644 index 00000000..f342c896 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_rtc.c @@ -0,0 +1,244 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_rtc.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the RTC firmware functions. +********************************************************************************/ +#include "ch32v30x_rtc.h" + +/* RTC_Private_Defines */ +#define RTC_LSB_MASK ((uint32_t)0x0000FFFF) /* RTC LSB Mask */ +#define PRLH_MSB_MASK ((uint32_t)0x000F0000) /* RTC Prescaler MSB Mask */ + +/******************************************************************************** +* Function Name : RTC_ITConfig +* Description : Enables or disables the specified RTC interrupts. +* Input : RTC_IT: specifies the RTC interrupts sources to be enabled or disabled. +* RTC_IT_OW: Overflow interrupt +* RTC_IT_ALR: Alarm interrupt +* RTC_IT_SEC: Second interrupt +* Return : NewState: new state of the specified RTC interrupts(ENABLE or DISABLE). +*********************************************************************************/ +void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + RTC->CTLRH |= RTC_IT; + } + else + { + RTC->CTLRH &= (uint16_t)~RTC_IT; + } +} + +/******************************************************************************** +* Function Name : RTC_EnterConfigMode +* Description : Enters the RTC configuration mode. +* Input : None +* Return : None +*********************************************************************************/ +void RTC_EnterConfigMode(void) +{ + RTC->CTLRL |= RTC_CTLRL_CNF; +} + +/******************************************************************************** +* Function Name : RTC_ExitConfigMode +* Description : Exits from the RTC configuration mode. +* Input : None +* Return : None +*********************************************************************************/ +void RTC_ExitConfigMode(void) +{ + RTC->CTLRL &= (uint16_t)~((uint16_t)RTC_CTLRL_CNF); +} + +/******************************************************************************** +* Function Name : RTC_GetCounter +* Description : Gets the RTC counter value +* Input : None +* Return : RTC counter value +*********************************************************************************/ +uint32_t RTC_GetCounter(void) +{ + uint16_t high1 = 0, high2 = 0, low = 0; + + high1 = RTC->CNTH; + low = RTC->CNTL; + high2 = RTC->CNTH; + + if (high1 != high2) + { + return (((uint32_t) high2 << 16 ) | RTC->CNTL); + } + else + { + return (((uint32_t) high1 << 16 ) | low); + } +} + +/******************************************************************************** +* Function Name : RTC_SetCounter +* Description : Sets the RTC counter value. +* Input : CounterValue: RTC counter new value. +* Return : None +*********************************************************************************/ +void RTC_SetCounter(uint32_t CounterValue) +{ + RTC_EnterConfigMode(); + RTC->CNTH = CounterValue >> 16; + RTC->CNTL = (CounterValue & RTC_LSB_MASK); + RTC_ExitConfigMode(); +} + +/******************************************************************************** +* Function Name : RTC_SetPrescaler +* Description : Sets the RTC prescaler value +* Input : PrescalerValue: RTC prescaler new value +* Return : None +*********************************************************************************/ +void RTC_SetPrescaler(uint32_t PrescalerValue) +{ + RTC_EnterConfigMode(); + RTC->PSCRH = (PrescalerValue & PRLH_MSB_MASK) >> 16; + RTC->PSCRL = (PrescalerValue & RTC_LSB_MASK); + RTC_ExitConfigMode(); +} + +/******************************************************************************** +* Function Name : RTC_SetAlarm +* Description : Sets the RTC alarm value +* Input : AlarmValue: RTC alarm new value +* Return : None +*********************************************************************************/ +void RTC_SetAlarm(uint32_t AlarmValue) +{ + RTC_EnterConfigMode(); + RTC->ALRMH = AlarmValue >> 16; + RTC->ALRML = (AlarmValue & RTC_LSB_MASK); + RTC_ExitConfigMode(); +} + +/******************************************************************************** +* Function Name : RTC_GetDivider +* Description : Gets the RTC divider value +* Input : None +* Return : RTC Divider value +*********************************************************************************/ +uint32_t RTC_GetDivider(void) +{ + uint32_t tmp = 0x00; + tmp = ((uint32_t)RTC->DIVH & (uint32_t)0x000F) << 16; + tmp |= RTC->DIVL; + return tmp; +} + +/******************************************************************************** +* Function Name : RTC_WaitForLastTask +* Description : Waits until last write operation on RTC registers has finished +* Input : None +* Return : None +*********************************************************************************/ +void RTC_WaitForLastTask(void) +{ + while ((RTC->CTLRL & RTC_FLAG_RTOFF) == (uint16_t)RESET) + { + } +} + +/******************************************************************************** +* Function Name : RTC_WaitForSynchro +* Description : Waits until the RTC registers +* are synchronized with RTC APB clock +* Input : None +* Return : None +*********************************************************************************/ +void RTC_WaitForSynchro(void) +{ + RTC->CTLRL &= (uint16_t)~RTC_FLAG_RSF; + while ((RTC->CTLRL & RTC_FLAG_RSF) == (uint16_t)RESET) + { + } +} + +/******************************************************************************** +* Function Name : RTC_GetFlagStatus +* Description : Checks whether the specified RTC flag is set or not +* Input : RTC_FLAG: specifies the flag to check +* RTC_FLAG_RTOFF: RTC Operation OFF flag +* RTC_FLAG_RSF: Registers Synchronized flag +* RTC_FLAG_OW: Overflow flag +* RTC_FLAG_ALR: Alarm flag +* RTC_FLAG_SEC: Second flag +* Return : The new state of RTC_FLAG (SET or RESET) +*********************************************************************************/ +FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG) +{ + FlagStatus bitstatus = RESET; + if ((RTC->CTLRL & RTC_FLAG) != (uint16_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************** +* Function Name : RTC_ClearFlag +* Description : Clears the RTC's pending flags +* Input : RTC_FLAG: specifies the flag to clear +* RTC_FLAG_RSF: Registers Synchronized flag +* RTC_FLAG_OW: Overflow flag +* RTC_FLAG_ALR: Alarm flag +* RTC_FLAG_SEC: Second flag +* Return : None +*********************************************************************************/ +void RTC_ClearFlag(uint16_t RTC_FLAG) +{ + RTC->CTLRL &= (uint16_t)~RTC_FLAG; +} + + +/******************************************************************************** +* Function Name : RTC_GetITStatus +* Description : Checks whether the specified RTC interrupt has occurred or not +* Input : RTC_IT: specifies the RTC interrupts sources to check +* RTC_FLAG_OW: Overflow interrupt +* RTC_FLAG_ALR: Alarm interrupt +* RTC_FLAG_SEC: Second interrupt +* Return : The new state of the RTC_IT (SET or RESET) +*********************************************************************************/ +ITStatus RTC_GetITStatus(uint16_t RTC_IT) +{ + ITStatus bitstatus = RESET; + + bitstatus = (ITStatus)(RTC->CTLRL & RTC_IT); + if (((RTC->CTLRH & RTC_IT) != (uint16_t)RESET) && (bitstatus != (uint16_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************** +* Function Name : RTC_ClearITPendingBit +* Description : Clears the RTC's interrupt pending bits +* Input : RTC_IT: specifies the interrupt pending bit to clear +* RTC_FLAG_OW: Overflow interrupt +* RTC_FLAG_ALR: Alarm interrupt +* RTC_FLAG_SEC: Second interrupt +* Return : None +*********************************************************************************/ +void RTC_ClearITPendingBit(uint16_t RTC_IT) +{ + RTC->CTLRL &= (uint16_t)~RTC_IT; +} + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_sdio.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_sdio.c new file mode 100644 index 00000000..7291c1ce --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_sdio.c @@ -0,0 +1,574 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_SDIO.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the SDIO firmware functions. +*******************************************************************************/ +#include "ch32v30x_sdio.h" +#include "ch32v30x_rcc.h" + + +#define SDIO_OFFSET (SDIO_BASE - PERIPH_BASE) + +/* CLKCR register clear mask */ +#define CLKCR_CLEAR_MASK ((uint32_t)0xFFFF8100) + +/* SDIO PWRCTRL Mask */ +#define PWR_PWRCTRL_MASK ((uint32_t)0xFFFFFFFC) + +/* SDIO DCTRL Clear Mask */ +#define DCTRL_CLEAR_MASK ((uint32_t)0xFFFFFF08) + +/* CMD Register clear mask */ +#define CMD_CLEAR_MASK ((uint32_t)0xFFFFF800) + +/* SDIO RESP Registers Address */ +#define SDIO_RESP_ADDR ((uint32_t)(SDIO_BASE + 0x14)) + +/******************************************************************************* +* Function Name : SDIO_DeInit +* Description : Deinitializes the SDIO peripheral registers to their default reset values. +* Input : None +* Return : None +*******************************************************************************/ +void SDIO_DeInit(void) +{ + SDIO->POWER = 0x00000000; + SDIO->CLKCR = 0x00000000; + SDIO->ARG = 0x00000000; + SDIO->CMD = 0x00000000; + SDIO->DTIMER = 0x00000000; + SDIO->DLEN = 0x00000000; + SDIO->DCTRL = 0x00000000; + SDIO->ICR = 0x00C007FF; + SDIO->MASK = 0x00000000; +} + +/******************************************************************************* +* Function Name : SDIO_Init +* Description : Initializes the SDIO peripheral according to the specified +* parameters in the SDIO_InitStruct. +* Input : SDIO_InitStruct : pointer to a SDIO_InitTypeDef structure +* that contains the configuration information for the SDIO peripheral. +* Return : None +*******************************************************************************/ +void SDIO_Init(SDIO_InitTypeDef* SDIO_InitStruct) +{ + uint32_t tmpreg = 0; + + tmpreg = SDIO->CLKCR; + tmpreg &= CLKCR_CLEAR_MASK; + tmpreg |= (SDIO_InitStruct->SDIO_ClockDiv | SDIO_InitStruct->SDIO_ClockPowerSave | + SDIO_InitStruct->SDIO_ClockBypass | SDIO_InitStruct->SDIO_BusWide | + SDIO_InitStruct->SDIO_ClockEdge | SDIO_InitStruct->SDIO_HardwareFlowControl); + + SDIO->CLKCR = tmpreg; +} + +/******************************************************************************* +* Function Name : SDIO_StructInit +* Description : Fills each SDIO_InitStruct member with its default value. +* Input : SDIO_InitStruct: pointer to an SDIO_InitTypeDef structure which +* will be initialized. +* Return : None +*******************************************************************************/ +void SDIO_StructInit(SDIO_InitTypeDef* SDIO_InitStruct) +{ + SDIO_InitStruct->SDIO_ClockDiv = 0x00; + SDIO_InitStruct->SDIO_ClockEdge = SDIO_ClockEdge_Rising; + SDIO_InitStruct->SDIO_ClockBypass = SDIO_ClockBypass_Disable; + SDIO_InitStruct->SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable; + SDIO_InitStruct->SDIO_BusWide = SDIO_BusWide_1b; + SDIO_InitStruct->SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable; +} + +/******************************************************************************* +* Function Name : SDIO_ClockCmd +* Description : Enables or disables the SDIO Clock. +* Input : SDIO_InitStruct: pointer to an SDIO_InitTypeDef structure which +* will be initialized. +* NewStateENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SDIO_ClockCmd(FunctionalState NewState) +{ + if(NewState) SDIO->CLKCR |= (1<<8); + else SDIO->CLKCR &= ~(1<<8); +} + +/******************************************************************************* +* Function Name : SDIO_SetPowerState +* Description : Sets the power status of the controller. +* Input : SDIO_PowerState: new state of the Power state. +* SDIO_PowerState_OFF +* SDIO_PowerState_ON +* Return : None +*******************************************************************************/ +void SDIO_SetPowerState(uint32_t SDIO_PowerState) +{ + + SDIO->POWER &= PWR_PWRCTRL_MASK; + SDIO->POWER |= SDIO_PowerState; +} + +/******************************************************************************* +* Function Name : SDIO_GetPowerState +* Description : Gets the power status of the controller. +* Input : None +* Return : +* - 0x00: Power OFF +* - 0x02: Power UP +* - 0x03: Power ON +*******************************************************************************/ +uint32_t SDIO_GetPowerState(void) +{ + return (SDIO->POWER & (~PWR_PWRCTRL_MASK)); +} + +/******************************************************************************* +* Function Name : SDIO_ITConfig +* Description : Enables or disables the SDIO interrupts. +* Input : DIO_IT: specifies the SDIO interrupt sources to be enabled or disabled. +* SDIO_IT_CCRCFAIL +* SDIO_IT_DCRCFAIL +* SDIO_IT_CTIMEOUT +* SDIO_IT_DTIMEOUT +* SDIO_IT_TXUNDERR +* SDIO_IT_RXOVERR +* SDIO_IT_CMDREND +* SDIO_IT_CMDSENT +* SDIO_IT_DATAEND +* SDIO_IT_STBITERR +* SDIO_IT_DBCKEND +* SDIO_IT_CMDACT +* SDIO_IT_TXACT +* SDIO_IT_RXACT +* SDIO_IT_TXFIFOHE +* SDIO_IT_RXFIFOHF +* SDIO_IT_TXFIFOF +* SDIO_IT_RXFIFOF +* SDIO_IT_TXFIFOE +* SDIO_IT_RXFIFOE +* SDIO_IT_TXDAVL +* SDIO_IT_RXDAVL +* SDIO_IT_SDIOIT +* SDIO_IT_CEATAEND +* NewState:ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SDIO_ITConfig(uint32_t SDIO_IT, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + SDIO->MASK |= SDIO_IT; + } + else + { + SDIO->MASK &= ~SDIO_IT; + } +} + +/******************************************************************************* +* Function Name : SDIO_DMACmd +* Description : Enables or disables the SDIO DMA request. +* Input : NewState:ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SDIO_DMACmd(FunctionalState NewState) +{ + if(NewState) SDIO->DCTRL |= (1<<3); + else SDIO->DCTRL &= ~(1<<3); +} + +/******************************************************************************* +* Function Name : SDIO_SendCommand +* Description : Initializes the SDIO Command according to the specified +* parameters in the SDIO_CmdInitStruct and send the command. +* Input : SDIO_CmdInitStruct : pointer to a SDIO_CmdInitTypeDef +* structure that contains the configuration information for the SDIO command. +* Return : None +*******************************************************************************/ +void SDIO_SendCommand(SDIO_CmdInitTypeDef *SDIO_CmdInitStruct) +{ + uint32_t tmpreg = 0; + + SDIO->ARG = SDIO_CmdInitStruct->SDIO_Argument; + + tmpreg = SDIO->CMD; + tmpreg &= CMD_CLEAR_MASK; + tmpreg |= (uint32_t)SDIO_CmdInitStruct->SDIO_CmdIndex | SDIO_CmdInitStruct->SDIO_Response + | SDIO_CmdInitStruct->SDIO_Wait | SDIO_CmdInitStruct->SDIO_CPSM; + + SDIO->CMD = tmpreg; +} + +/******************************************************************************* +* Function Name : SDIO_CmdStructInit +* Description : Fills each SDIO_CmdInitStruct member with its default value. +* Input : SDIO_CmdInitStruct: pointer to an SDIO_CmdInitTypeDef +* structure which will be initialized. +* Return : None +*******************************************************************************/ +void SDIO_CmdStructInit(SDIO_CmdInitTypeDef* SDIO_CmdInitStruct) +{ + SDIO_CmdInitStruct->SDIO_Argument = 0x00; + SDIO_CmdInitStruct->SDIO_CmdIndex = 0x00; + SDIO_CmdInitStruct->SDIO_Response = SDIO_Response_No; + SDIO_CmdInitStruct->SDIO_Wait = SDIO_Wait_No; + SDIO_CmdInitStruct->SDIO_CPSM = SDIO_CPSM_Disable; +} + +/******************************************************************************* +* Function Name : SDIO_GetCommandResponse +* Description : Returns command index of last command for which response received. +* Input : None +* Return : Returns the command index of the last command response received. +*******************************************************************************/ +uint8_t SDIO_GetCommandResponse(void) +{ + return (uint8_t)(SDIO->RESPCMD); +} + + +/******************************************************************************* +* Function Name : SDIO_GetResponse +* Description : Returns response received from the card for the last command. +* Input : SDIO_RESP: Specifies the SDIO response register. +* SDIO_RESP1: Response Register 1 +* SDIO_RESP2: Response Register 2 +* SDIO_RESP3: Response Register 3 +* SDIO_RESP4: Response Register 4 +* Return : Returns the command index of the last command response received. +*******************************************************************************/ +uint32_t SDIO_GetResponse(uint32_t SDIO_RESP) +{ + __IO uint32_t tmp = 0; + + tmp = SDIO_RESP_ADDR + SDIO_RESP; + + return (*(__IO uint32_t *) tmp); +} + +/******************************************************************************* +* Function Name : SDIO_DataConfig +* Description : Initializes the SDIO data path according to the specified +* Input : SDIO_DataInitStruct : pointer to a SDIO_DataInitTypeDef structure that +* contains the configuration information for the SDIO command. +* Return : None +*******************************************************************************/ +void SDIO_DataConfig(SDIO_DataInitTypeDef* SDIO_DataInitStruct) +{ + uint32_t tmpreg = 0; + + SDIO->DTIMER = SDIO_DataInitStruct->SDIO_DataTimeOut; + SDIO->DLEN = SDIO_DataInitStruct->SDIO_DataLength; + tmpreg = SDIO->DCTRL; + tmpreg &= DCTRL_CLEAR_MASK; + tmpreg |= (uint32_t)SDIO_DataInitStruct->SDIO_DataBlockSize | SDIO_DataInitStruct->SDIO_TransferDir + | SDIO_DataInitStruct->SDIO_TransferMode | SDIO_DataInitStruct->SDIO_DPSM; + + SDIO->DCTRL = tmpreg; +} + +/******************************************************************************* +* Function Name : SDIO_DataStructInit +* Description : Fills each SDIO_DataInitStruct member with its default value. +* Input : SDIO_DataInitStruct: pointer to an SDIO_DataInitTypeDef structure which +* will be initialized. +* Return : None +*******************************************************************************/ +void SDIO_DataStructInit(SDIO_DataInitTypeDef* SDIO_DataInitStruct) +{ + SDIO_DataInitStruct->SDIO_DataTimeOut = 0xFFFFFFFF; + SDIO_DataInitStruct->SDIO_DataLength = 0x00; + SDIO_DataInitStruct->SDIO_DataBlockSize = SDIO_DataBlockSize_1b; + SDIO_DataInitStruct->SDIO_TransferDir = SDIO_TransferDir_ToCard; + SDIO_DataInitStruct->SDIO_TransferMode = SDIO_TransferMode_Block; + SDIO_DataInitStruct->SDIO_DPSM = SDIO_DPSM_Disable; +} + +/******************************************************************************* +* Function Name : SDIO_GetDataCounter +* Description : Returns number of remaining data bytes to be transferred. +* Input : None +* Return : Number of remaining data bytes to be transferred +*******************************************************************************/ +uint32_t SDIO_GetDataCounter(void) +{ + return SDIO->DCOUNT; +} + +/******************************************************************************* +* Function Name : SDIO_ReadData +* Description : Read one data word from Rx FIFO. +* Input : None +* Return : Data received +*******************************************************************************/ +uint32_t SDIO_ReadData(void) +{ + return SDIO->FIFO; +} + +/******************************************************************************* +* Function Name : SDIO_WriteData +* Description : Write one data word to Tx FIFO. +* Input : Data: 32-bit data word to write. +* Return : None +*******************************************************************************/ +void SDIO_WriteData(uint32_t Data) +{ + SDIO->FIFO = Data; +} + +/******************************************************************************* +* Function Name : SDIO_GetFIFOCount +* Description : Returns the number of words left to be written to or read from FIFO. +* Input : None +* Return : Remaining number of words. +*******************************************************************************/ +uint32_t SDIO_GetFIFOCount(void) +{ + return SDIO->FIFOCNT; +} + +/******************************************************************************* +* Function Name : SDIO_StartSDIOReadWait +* Description : Starts the SD I/O Read Wait operation. +* Input : NewStateENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SDIO_StartSDIOReadWait(FunctionalState NewState) +{ + if(NewState) SDIO->DCTRL |= (1<<8); + else SDIO->DCTRL &= ~(1<<8); +} + +/******************************************************************************* +* Function Name : SDIO_StopSDIOReadWait +* Description : Stops the SD I/O Read Wait operation. +* Input : NewStateENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SDIO_StopSDIOReadWait(FunctionalState NewState) +{ + if(NewState) SDIO->DCTRL |= (1<<9); + else SDIO->DCTRL &= ~(1<<9); + +} + +/******************************************************************************* +* Function Name : SDIO_SetSDIOReadWaitMode +* Description : Sets one of the two options of inserting read wait interval. +* Input : SDIO_ReadWaitMode: SD I/O Read Wait operation mode. +* SDIO_ReadWaitMode_CLK: Read Wait control by stopping SDIOCLK +* SDIO_ReadWaitMode_DATA2: Read Wait control using SDIO_DATA2 +* Return : None +*******************************************************************************/ +void SDIO_SetSDIOReadWaitMode(uint32_t SDIO_ReadWaitMode) +{ + if(SDIO_ReadWaitMode) SDIO->DCTRL |= (1<<10); + else SDIO->DCTRL &= ~(1<<10); +} + +/******************************************************************************* +* Function Name : SDIO_SetSDIOOperation +* Description : Enables or disables the SD I/O Mode Operation. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SDIO_SetSDIOOperation(FunctionalState NewState) +{ + if(NewState) SDIO->DCTRL |= (1<<11); + else SDIO->DCTRL &= ~(1<<11); +} + +/******************************************************************************* +* Function Name : SDIO_SendSDIOSuspendCmd +* Description : Enables or disables the SD I/O Mode suspend command sending. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SDIO_SendSDIOSuspendCmd(FunctionalState NewState) +{ + if(NewState) SDIO->CMD |= (1<<11); + else SDIO->CMD &= ~(1<<11); +} + +/******************************************************************************* +* Function Name : SDIO_CommandCompletionCmd +* Description : Enables or disables the command completion signal. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SDIO_CommandCompletionCmd(FunctionalState NewState) +{ + if(NewState) SDIO->CMD |= (1<<12); + else SDIO->CMD &= ~(1<<12); +} + +/******************************************************************************* +* Function Name : SDIO_CEATAITCmd +* Description : Enables or disables the CE-ATA interrupt. +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SDIO_CEATAITCmd(FunctionalState NewState) +{ + if(NewState) SDIO->CMD |= (1<<13); + else SDIO->CMD &= ~(1<<13); +} + +/******************************************************************************* +* Function Name : SDIO_SendCEATACmd +* Description : Sends CE-ATA command (CMD61). +* Input : NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SDIO_SendCEATACmd(FunctionalState NewState) +{ + if(NewState) SDIO->CMD |= (1<<14); + else SDIO->CMD &= ~(1<<14); +} + +/******************************************************************************* +* Function Name : SDIO_GetFlagStatus +* Description : Checks whether the specified SDIO flag is set or not. +* Input : SDIO_FLAG: specifies the flag to check. +* SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) +* SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed) +* SDIO_FLAG_CTIMEOUT: Command response timeout +* SDIO_FLAG_DTIMEOUT: Data timeout +* SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error +* SDIO_FLAG_RXOVERR: Received FIFO overrun error +* SDIO_FLAG_CMDREND: Command response received (CRC check passed) +* SDIO_FLAG_CMDSENT: Command sent (no response required) +* SDIO_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero) +* SDIO_FLAG_STBITERR: Start bit not detected on all data signals in wide +* bus mode. +* SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed) +* SDIO_FLAG_CMDACT: Command transfer in progress +* SDIO_FLAG_TXACT: Data transmit in progress +* SDIO_FLAG_RXACT: Data receive in progress +* SDIO_FLAG_TXFIFOHE: Transmit FIFO Half Empty +* SDIO_FLAG_RXFIFOHF: Receive FIFO Half Full +* SDIO_FLAG_TXFIFOF: Transmit FIFO full +* SDIO_FLAG_RXFIFOF: Receive FIFO full +* SDIO_FLAG_TXFIFOE: Transmit FIFO empty +* SDIO_FLAG_RXFIFOE: Receive FIFO empty +* SDIO_FLAG_TXDAVL: Data available in transmit FIFO +* SDIO_FLAG_RXDAVL: Data available in receive FIFO +* SDIO_FLAG_SDIOIT: SD I/O interrupt received +* SDIO_FLAG_CEATAEND: CE-ATA command completion signal received for CMD61 +* Return : ITStatusSET or RESET +*******************************************************************************/ +FlagStatus SDIO_GetFlagStatus(uint32_t SDIO_FLAG) +{ + FlagStatus bitstatus = RESET; + + if ((SDIO->STA & SDIO_FLAG) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + + +/******************************************************************************* +* Function Name : SDIO_ClearFlag +* Description : Clears the SDIO's pending flags. +* Input : SDIO_FLAG: specifies the flag to clear. +* SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed) +* SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed) +* SDIO_FLAG_CTIMEOUT: Command response timeout +* SDIO_FLAG_DTIMEOUT: Data timeout +* SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error +* SDIO_FLAG_RXOVERR: Received FIFO overrun error +* SDIO_FLAG_CMDREND: Command response received (CRC check passed) +* SDIO_FLAG_CMDSENT: Command sent (no response required) +* SDIO_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero) +* SDIO_FLAG_STBITERR: Start bit not detected on all data signals in wide +* bus mode +* SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed) +* SDIO_FLAG_SDIOIT: SD I/O interrupt received +* SDIO_FLAG_CEATAEND: CE-ATA command completion signal received for CMD61 +* Return : None +*******************************************************************************/ +void SDIO_ClearFlag(uint32_t SDIO_FLAG) +{ + SDIO->ICR = SDIO_FLAG; +} + +/******************************************************************************* +* Function Name : SDIO_GetITStatus +* Description : Checks whether the specified SDIO interrupt has occurred or not. +* Input : SDIO_IT: specifies the SDIO interrupt source to check. +* SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt +* SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt +* SDIO_IT_CTIMEOUT: Command response timeout interrupt +* SDIO_IT_DTIMEOUT: Data timeout interrupt +* SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt +* SDIO_IT_RXOVERR: Received FIFO overrun error interrupt +* SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt +* SDIO_IT_CMDSENT: Command sent (no response required) interrupt +* SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt +* SDIO_IT_STBITERR: Start bit not detected on all data signals in wide +* bus mode interrupt +* SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt +* SDIO_IT_CMDACT: Command transfer in progress interrupt +* SDIO_IT_TXACT: Data transmit in progress interrupt +* SDIO_IT_RXACT: Data receive in progress interrupt +* SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt +* SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt +* SDIO_IT_TXFIFOF: Transmit FIFO full interrupt +* SDIO_IT_RXFIFOF: Receive FIFO full interrupt +* SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt +* SDIO_IT_RXFIFOE: Receive FIFO empty interrupt +* SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt +* SDIO_IT_RXDAVL: Data available in receive FIFO interrupt +* SDIO_IT_SDIOIT: SD I/O interrupt received interrupt +* SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 interrupt +* Return : ITStatusSET or RESET +*******************************************************************************/ +ITStatus SDIO_GetITStatus(uint32_t SDIO_IT) +{ + ITStatus bitstatus = RESET; + + if ((SDIO->STA & SDIO_IT) != (uint32_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + return bitstatus; +} + +/******************************************************************************* +* Function Name : SDIO_ClearITPendingBit +* Description : Clears the SDIO's interrupt pending bits. +* Input : SDIO_IT: specifies the interrupt pending bit to clear. +* SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt +* SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt +* SDIO_IT_CTIMEOUT: Command response timeout interrupt +* SDIO_IT_DTIMEOUT: Data timeout interrupt +* SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt +* SDIO_IT_RXOVERR: Received FIFO overrun error interrupt +* SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt +* SDIO_IT_CMDSENT: Command sent (no response required) interrupt +* SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt +* SDIO_IT_STBITERR: Start bit not detected on all data signals in wide +* bus mode interrupt +* SDIO_IT_SDIOIT: SD I/O interrupt received interrupt +* SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 +* Return : None +*******************************************************************************/ +void SDIO_ClearITPendingBit(uint32_t SDIO_IT) +{ + SDIO->ICR = SDIO_IT; +} diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_spi.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_spi.c new file mode 100644 index 00000000..06b54210 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_spi.c @@ -0,0 +1,587 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_spi.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the SPI firmware functions. +*********************************************************************************/ +#include "ch32v30x_spi.h" +#include "ch32v30x_rcc.h" + +/* SPI SPE mask */ +#define CTLR1_SPE_Set ((uint16_t)0x0040) +#define CTLR1_SPE_Reset ((uint16_t)0xFFBF) + +/* I2S I2SE mask */ +#define I2SCFGR_I2SE_Set ((uint16_t)0x0400) +#define I2SCFGR_I2SE_Reset ((uint16_t)0xFBFF) + +/* SPI CRCNext mask */ +#define CTLR1_CRCNext_Set ((uint16_t)0x1000) + +/* SPI CRCEN mask */ +#define CTLR1_CRCEN_Set ((uint16_t)0x2000) +#define CTLR1_CRCEN_Reset ((uint16_t)0xDFFF) + +/* SPI SSOE mask */ +#define CTLR2_SSOE_Set ((uint16_t)0x0004) +#define CTLR2_SSOE_Reset ((uint16_t)0xFFFB) + +/* SPI registers Masks */ +#define CTLR1_CLEAR_Mask ((uint16_t)0x3040) +#define I2SCFGR_CLEAR_Mask ((uint16_t)0xF040) + +/* SPI or I2S mode selection masks */ +#define SPI_Mode_Select ((uint16_t)0xF7FF) +#define I2S_Mode_Select ((uint16_t)0x0800) + +/* I2S clock source selection masks */ +#define I2S2_CLOCK_SRC ((uint32_t)(0x00020000)) +#define I2S3_CLOCK_SRC ((uint32_t)(0x00040000)) +#define I2S_MUL_MASK ((uint32_t)(0x0000F000)) +#define I2S_DIV_MASK ((uint32_t)(0x000000F0)) + +/******************************************************************************* +* Function Name : SPI_I2S_DeInit +* Description : Deinitializes the SPIx peripheral registers to their default +* reset values (Affects also the I2Ss). +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* Return : None +*******************************************************************************/ +void SPI_I2S_DeInit(SPI_TypeDef* SPIx) +{ + if (SPIx == SPI1) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE); + } + else if (SPIx == SPI2) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE); + } + else + { + if (SPIx == SPI3) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, DISABLE); + } + } +} + +/******************************************************************************* +* Function Name : SPI_Init +* Description : Initializes the SPIx peripheral according to the specified +* parameters in the SPI_InitStruct. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* SPI_InitStruct: pointer to a SPI_InitTypeDef structure that +* contains the configuration information for the specified SPI peripheral. +* Return : None +*******************************************************************************/ +void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct) +{ + uint16_t tmpreg = 0; + + tmpreg = SPIx->CTLR1; + tmpreg &= CTLR1_CLEAR_Mask; + tmpreg |= (uint16_t)((uint32_t)SPI_InitStruct->SPI_Direction | SPI_InitStruct->SPI_Mode | + SPI_InitStruct->SPI_DataSize | SPI_InitStruct->SPI_CPOL | + SPI_InitStruct->SPI_CPHA | SPI_InitStruct->SPI_NSS | + SPI_InitStruct->SPI_BaudRatePrescaler | SPI_InitStruct->SPI_FirstBit); + + SPIx->CTLR1 = tmpreg; + SPIx->I2SCFGR &= SPI_Mode_Select; + SPIx->CRCR = SPI_InitStruct->SPI_CRCPolynomial; +} + +/******************************************************************************* +* Function Name : I2S_Init +* Description : Initializes the SPIx peripheral according to the specified +* parameters in the I2S_InitStruct. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* (configured in I2S mode). +* I2S_InitStruct: pointer to an I2S_InitTypeDef structure that +* contains the configuration information for the specified SPI peripheral +* configured in I2S mode. +* Return : None +*******************************************************************************/ +void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct) +{ + uint16_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1; + uint32_t tmp = 0; + RCC_ClocksTypeDef RCC_Clocks; + uint32_t sourceclock = 0; + + SPIx->I2SCFGR &= I2SCFGR_CLEAR_Mask; + SPIx->I2SPR = 0x0002; + tmpreg = SPIx->I2SCFGR; + + if(I2S_InitStruct->I2S_AudioFreq == I2S_AudioFreq_Default) + { + i2sodd = (uint16_t)0; + i2sdiv = (uint16_t)2; + } + else + { + if(I2S_InitStruct->I2S_DataFormat == I2S_DataFormat_16b) + { + packetlength = 1; + } + else + { + packetlength = 2; + } + + if(((uint32_t)SPIx) == SPI2_BASE) + { + tmp = I2S2_CLOCK_SRC; + } + else + { + tmp = I2S3_CLOCK_SRC; + } + + RCC_GetClocksFreq(&RCC_Clocks); + + sourceclock = RCC_Clocks.SYSCLK_Frequency; + + if(I2S_InitStruct->I2S_MCLKOutput == I2S_MCLKOutput_Enable) + { + tmp = (uint16_t)(((((sourceclock / 256) * 10) / I2S_InitStruct->I2S_AudioFreq)) + 5); + } + else + { + tmp = (uint16_t)(((((sourceclock / (32 * packetlength)) *10 ) / I2S_InitStruct->I2S_AudioFreq)) + 5); + } + + tmp = tmp / 10; + i2sodd = (uint16_t)(tmp & (uint16_t)0x0001); + i2sdiv = (uint16_t)((tmp - i2sodd) / 2); + i2sodd = (uint16_t) (i2sodd << 8); + } + + if ((i2sdiv < 2) || (i2sdiv > 0xFF)) + { + i2sdiv = 2; + i2sodd = 0; + } + + SPIx->I2SPR = (uint16_t)(i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->I2S_MCLKOutput)); + tmpreg |= (uint16_t)(I2S_Mode_Select | (uint16_t)(I2S_InitStruct->I2S_Mode | \ + (uint16_t)(I2S_InitStruct->I2S_Standard | (uint16_t)(I2S_InitStruct->I2S_DataFormat | \ + (uint16_t)I2S_InitStruct->I2S_CPOL)))); + SPIx->I2SCFGR = tmpreg; +} + +/******************************************************************************* +* Function Name : SPI_StructInit +* Description : Fills each SPI_InitStruct member with its default value. +* Input : SPI_InitStruct : pointer to a SPI_InitTypeDef structure which +* will be initialized. +* Return : None +*******************************************************************************/ +void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct) +{ + SPI_InitStruct->SPI_Direction = SPI_Direction_2Lines_FullDuplex; + SPI_InitStruct->SPI_Mode = SPI_Mode_Slave; + SPI_InitStruct->SPI_DataSize = SPI_DataSize_8b; + SPI_InitStruct->SPI_CPOL = SPI_CPOL_Low; + SPI_InitStruct->SPI_CPHA = SPI_CPHA_1Edge; + SPI_InitStruct->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; + SPI_InitStruct->SPI_FirstBit = SPI_FirstBit_MSB; + SPI_InitStruct->SPI_CRCPolynomial = 7; +} + +/******************************************************************************* +* Function Name : I2S_StructInit +* Description : Fills each I2S_InitStruct member with its default value. +* Input : I2S_InitStruct : pointer to a I2S_InitTypeDef structure which +* will be initialized. +* Return : None +*******************************************************************************/ +void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct) +{ + I2S_InitStruct->I2S_Mode = I2S_Mode_SlaveTx; + I2S_InitStruct->I2S_Standard = I2S_Standard_Phillips; + I2S_InitStruct->I2S_DataFormat = I2S_DataFormat_16b; + I2S_InitStruct->I2S_MCLKOutput = I2S_MCLKOutput_Disable; + I2S_InitStruct->I2S_AudioFreq = I2S_AudioFreq_Default; + I2S_InitStruct->I2S_CPOL = I2S_CPOL_Low; +} + +/******************************************************************************* +* Function Name : SPI_Cmd +* Description : Enables or disables the specified SPI peripheral. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + SPIx->CTLR1 |= CTLR1_SPE_Set; + } + else + { + SPIx->CTLR1 &= CTLR1_SPE_Reset; + } +} + +/******************************************************************************* +* Function Name : I2S_Cmd +* Description : Enables or disables the specified SPI peripheral (in I2S mode). +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + SPIx->I2SCFGR |= I2SCFGR_I2SE_Set; + } + else + { + SPIx->I2SCFGR &= I2SCFGR_I2SE_Reset; + } +} + +/******************************************************************************* +* Function Name : SPI_I2S_ITConfig +* Description : Enables or disables the specified SPI/I2S interrupts. +* Input : SPIx: where x can be +* - 1, 2 or 3 in SPI mode. +* - 2 or 3 in I2S mode. +* SPI_I2S_IT: specifies the SPI/I2S interrupt source to be +* enabled or disabled. +* SPI_I2S_IT_TXE: Tx buffer empty interrupt mask. +* SPI_I2S_IT_RXNE: Rx buffer not empty interrupt mask. +* SPI_I2S_IT_ERR: Error interrupt mask. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState) +{ + uint16_t itpos = 0, itmask = 0 ; + + itpos = SPI_I2S_IT >> 4; + itmask = (uint16_t)1 << (uint16_t)itpos; + + if (NewState != DISABLE) + { + SPIx->CTLR2 |= itmask; + } + else + { + SPIx->CTLR2 &= (uint16_t)~itmask; + } +} + +/******************************************************************************* +* Function Name : SPI_I2S_DMACmd +* Description : Enables or disables the SPIx/I2Sx DMA interface. +* Input : SPIx: where x can be +* - 1, 2 or 3 in SPI mode. +* - 2 or 3 in I2S mode. +* SPI_I2S_DMAReq: specifies the SPI/I2S DMA transfer request to +* be enabled or disabled. +* SPI_I2S_DMAReq_Tx: Tx buffer DMA transfer request. +* SPI_I2S_DMAReq_Rx: Rx buffer DMA transfer request. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + SPIx->CTLR2 |= SPI_I2S_DMAReq; + } + else + { + SPIx->CTLR2 &= (uint16_t)~SPI_I2S_DMAReq; + } +} + +/******************************************************************************* +* Function Name : SPI_I2S_SendData +* Description : Transmits a Data through the SPIx/I2Sx peripheral. +* Input : SPIx: where x can be +* - 1, 2 or 3 in SPI mode. +* - 2 or 3 in I2S mode. +* Data : Data to be transmitted. +* Return : None +*******************************************************************************/ +void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data) +{ + SPIx->DATAR = Data; +} + +/******************************************************************************* +* Function Name : SPI_I2S_ReceiveData +* Description : Returns the most recent received data by the SPIx/I2Sx peripheral. +* Input : SPIx: where x can be +* - 1, 2 or 3 in SPI mode. +* - 2 or 3 in I2S mode. +* Data : Data to be transmitted. +* Return : SPIx->DATAR: The value of the received data. +*******************************************************************************/ +uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) +{ + return SPIx->DATAR; +} + +/******************************************************************************* +* Function Name : SPI_NSSInternalSoftwareConfig +* Description : Configures internally by software the NSS pin for the selected SPI. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* SPI_NSSInternalSoft: +* SPI_NSSInternalSoft_Set: Set NSS pin internally. +* SPI_NSSInternalSoft_Reset: Reset NSS pin internally. +* Return : None +*******************************************************************************/ +void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft) +{ + if (SPI_NSSInternalSoft != SPI_NSSInternalSoft_Reset) + { + SPIx->CTLR1 |= SPI_NSSInternalSoft_Set; + } + else + { + SPIx->CTLR1 &= SPI_NSSInternalSoft_Reset; + } +} + +/******************************************************************************* +* Function Name : SPI_SSOutputCmd +* Description : Enables or disables the SS output for the selected SPI. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* NewState: new state of the SPIx SS output. +* Return : None +*******************************************************************************/ +void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + SPIx->CTLR2 |= CTLR2_SSOE_Set; + } + else + { + SPIx->CTLR2 &= CTLR2_SSOE_Reset; + } +} + +/******************************************************************************* +* Function Name : SPI_DataSizeConfig +* Description : Configures the data size for the selected SPI. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* SPI_DataSize: specifies the SPI data size. +* SPI_DataSize_16b: Set data frame format to 16bit. +* SPI_DataSize_8b: Set data frame format to 8bit. +* Return : None +*******************************************************************************/ +void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize) +{ + SPIx->CTLR1 &= (uint16_t)~SPI_DataSize_16b; + SPIx->CTLR1 |= SPI_DataSize; +} + +/******************************************************************************* +* Function Name : SPI_TransmitCRC +* Description : Transmit the SPIx CRC value. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* Return : None +*******************************************************************************/ +void SPI_TransmitCRC(SPI_TypeDef* SPIx) +{ + SPIx->CTLR1 |= CTLR1_CRCNext_Set; +} + +/******************************************************************************* +* Function Name : SPI_CalculateCRC +* Description : Enables or disables the CRC value calculation of the transferred bytes. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* NewState: new state of the SPIx CRC value calculation. +* Return : None +*******************************************************************************/ +void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + SPIx->CTLR1 |= CTLR1_CRCEN_Set; + } + else + { + SPIx->CTLR1 &= CTLR1_CRCEN_Reset; + } +} + +/******************************************************************************* +* Function Name : SPI_GetCRC +* Description : Returns the transmit or the receive CRC register value for the specified SPI. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* SPI_CRC: specifies the CRC register to be read. +* SPI_CRC_Tx: Selects Tx CRC register. +* SPI_CRC_Rx: Selects Rx CRC register. +* Return : crcreg: The selected CRC register value. +*******************************************************************************/ +uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC) +{ + uint16_t crcreg = 0; + + if (SPI_CRC != SPI_CRC_Rx) + { + crcreg = SPIx->TCRCR; + } + else + { + crcreg = SPIx->RCRCR; + } + + return crcreg; +} + +/******************************************************************************* +* Function Name : SPI_GetCRCPolynomial +* Description : Returns the CRC Polynomial register value for the specified SPI. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* Return : SPIx->CRCR: The CRC Polynomial register value. +*******************************************************************************/ +uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx) +{ + return SPIx->CRCR; +} + +/******************************************************************************* +* Function Name : SPI_BiDirectionalLineConfig +* Description : Selects the data transfer direction in bi-directional mode +* for the specified SPI. +* Input : SPIx: where x can be 1, 2 or 3 to select the SPI peripheral. +* SPI_Direction: specifies the data transfer direction in +* bi-directional mode. +* SPI_Direction_Tx: Selects Tx transmission direction. +* SPI_Direction_Rx: Selects Rx receive direction. +* Return : None +*******************************************************************************/ +void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction) +{ + if (SPI_Direction == SPI_Direction_Tx) + { + SPIx->CTLR1 |= SPI_Direction_Tx; + } + else + { + SPIx->CTLR1 &= SPI_Direction_Rx; + } +} + +/******************************************************************************* +* Function Name : SPI_I2S_GetFlagStatus +* Description : Checks whether the specified SPI/I2S flag is set or not. +* Input : SPIx: where x can be +* - 1, 2 or 3 in SPI mode. +* - 2 or 3 in I2S mode. +* SPI_I2S_FLAG: specifies the SPI/I2S flag to check. +* SPI_I2S_FLAG_TXE: Transmit buffer empty flag. +* SPI_I2S_FLAG_RXNE: Receive buffer not empty flag. +* SPI_I2S_FLAG_BSY: Busy flag. +* SPI_I2S_FLAG_OVR: Overrun flag. +* SPI_FLAG_MODF: Mode Fault flag. +* SPI_FLAG_CRCERR: CRC Error flag. +* I2S_FLAG_UDR: Underrun Error flag. +* I2S_FLAG_CHSIDE: Channel Side flag. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG) +{ + FlagStatus bitstatus = RESET; + + if ((SPIx->STATR & SPI_I2S_FLAG) != (uint16_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : SPI_I2S_ClearFlag +* Description : Clears the SPIx CRC Error (CRCERR) flag. +* Input : SPIx: where x can be +* - 1, 2 or 3 in SPI mode. +* - 2 or 3 in I2S mode. +* SPI_I2S_FLAG: specifies the SPI flag to clear. +* SPI_FLAG_CRCERR: CRC Error flag. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG) +{ + SPIx->STATR = (uint16_t)~SPI_I2S_FLAG; +} + +/******************************************************************************* +* Function Name : SPI_I2S_GetITStatus +* Description : Checks whether the specified SPI/I2S interrupt has occurred or not. +* Input : SPIx: where x can be +* - 1, 2 or 3 in SPI mode. +* - 2 or 3 in I2S mode. +* SPI_I2S_IT: specifies the SPI/I2S interrupt source to check.. +* SPI_I2S_IT_TXE: Transmit buffer empty interrupt. +* SPI_I2S_IT_RXNE: Receive buffer not empty interrupt. +* SPI_I2S_IT_OVR: Overrun interrupt. +* SPI_IT_MODF: Mode Fault interrupt. +* SPI_IT_CRCERR: CRC Error interrupt. +* I2S_IT_UDR: Underrun Error interrupt. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT) +{ + ITStatus bitstatus = RESET; + uint16_t itpos = 0, itmask = 0, enablestatus = 0; + + itpos = 0x01 << (SPI_I2S_IT & 0x0F); + itmask = SPI_I2S_IT >> 4; + itmask = 0x01 << itmask; + enablestatus = (SPIx->CTLR2 & itmask) ; + + if (((SPIx->STATR & itpos) != (uint16_t)RESET) && enablestatus) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : SPI_I2S_ClearITPendingBit +* Description : Clears the SPIx CRC Error (CRCERR) interrupt pending bit. +* Input : SPIx: where x can be +* - 1, 2 or 3 in SPI mode. +* SPI_I2S_IT: specifies the SPI interrupt pending bit to clear. +* SPI_IT_CRCERR: CRC Error interrupt. +* Return : FlagStatus: SET or RESET. +*******************************************************************************/ +void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT) +{ + uint16_t itpos = 0; + + itpos = 0x01 << (SPI_I2S_IT & 0x0F); + SPIx->STATR = (uint16_t)~itpos; +} + + + + + + + + diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_tim.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_tim.c new file mode 100644 index 00000000..19ae44a7 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_tim.c @@ -0,0 +1,2117 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_tim.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the TIM firmware functions. +*******************************************************************************/ +#include "ch32v30x_tim.h" +#include "ch32v30x_rcc.h" + +/* TIM registers bit mask */ +#define SMCFGR_ETR_Mask ((uint16_t)0x00FF) +#define CHCTLR_Offset ((uint16_t)0x0018) +#define CCER_CCE_Set ((uint16_t)0x0001) +#define CCER_CCNE_Set ((uint16_t)0x0004) + +static void TI1_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +static void TI2_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +static void TI3_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); +static void TI4_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter); + +/******************************************************************************* +* Function Name : TIM_DeInit +* Description : Deinitializes the TIMx peripheral registers to their default +* reset values. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* Return : None +*******************************************************************************/ +void TIM_DeInit(TIM_TypeDef* TIMx) +{ + if (TIMx == TIM1) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, DISABLE); + } + else if (TIMx == TIM8) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, DISABLE); + } + else if (TIMx == TIM9) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, DISABLE); + } + else if (TIMx == TIM10) + { + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, ENABLE); + RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, DISABLE); + } + else if (TIMx == TIM2) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, DISABLE); + } + else if (TIMx == TIM3) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, DISABLE); + } + else if (TIMx == TIM4) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, DISABLE); + } + else if (TIMx == TIM5) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, DISABLE); + } + else if (TIMx == TIM6) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, DISABLE); + } + else if (TIMx == TIM7) + { + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, DISABLE); + } +} + +/******************************************************************************* +* Function Name : TIM_TimeBaseInit +* Description : Initializes the TIMx Time Base Unit peripheral according to +* the specified parameters in the TIM_TimeBaseInitStruct. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_TimeBaseInitStruct: pointer to a TIM_TimeBaseInitTypeDef +* structure. +* Return : None +*******************************************************************************/ +void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) +{ + uint16_t tmpcr1 = 0; + + tmpcr1 = TIMx->CTLR1; + + if((TIMx == TIM1) || (TIMx == TIM2) || (TIMx == TIM3)|| (TIMx == TIM4) || + (TIMx == TIM5) || (TIMx == TIM8) || (TIMx == TIM9)|| (TIMx == TIM10)) + { + tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_DIR | TIM_CMS))); + tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode; + } + + if((TIMx != TIM6) && (TIMx != TIM7)) + { + tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CTLR1_CKD)); + tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision; + } + + TIMx->CTLR1 = tmpcr1; + TIMx->ATRLR = TIM_TimeBaseInitStruct->TIM_Period ; + TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler; + + if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM9)|| (TIMx == TIM10)) + { + TIMx->RPTCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter; + } + + TIMx->SWEVGR = TIM_PSCReloadMode_Immediate; +} + +/******************************************************************************* +* Function Name : TIM_OC1Init +* Description : Initializes the TIMx Channel1 according to the specified +* parameters in the TIM_OCInitStruct. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0; + + TIMx->CCER &= (uint16_t)(~(uint16_t)TIM_CC1E); + tmpccer = TIMx->CCER; + tmpcr2 = TIMx->CTLR2; + tmpccmrx = TIMx->CHCTLR1; + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_OC1M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CC1S)); + tmpccmrx |= TIM_OCInitStruct->TIM_OCMode; + tmpccer &= (uint16_t)(~((uint16_t)TIM_CC1P)); + tmpccer |= TIM_OCInitStruct->TIM_OCPolarity; + tmpccer |= TIM_OCInitStruct->TIM_OutputState; + + if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM9)|| (TIMx == TIM10)) + { + tmpccer &= (uint16_t)(~((uint16_t)TIM_CC1NP)); + tmpccer |= TIM_OCInitStruct->TIM_OCNPolarity; + + tmpccer &= (uint16_t)(~((uint16_t)TIM_CC1NE)); + tmpccer |= TIM_OCInitStruct->TIM_OutputNState; + + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_OIS1)); + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_OIS1N)); + + tmpcr2 |= TIM_OCInitStruct->TIM_OCIdleState; + tmpcr2 |= TIM_OCInitStruct->TIM_OCNIdleState; + } + + TIMx->CTLR2 = tmpcr2; + TIMx->CHCTLR1 = tmpccmrx; + TIMx->CH1CVR = TIM_OCInitStruct->TIM_Pulse; + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_OC2Init +* Description : Initializes the TIMx Channel2 according to the specified +* parameters in the TIM_OCInitStruct. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0; + + TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CC2E)); + tmpccer = TIMx->CCER; + tmpcr2 = TIMx->CTLR2; + tmpccmrx = TIMx->CHCTLR1; + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_OC2M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CC2S)); + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->TIM_OCMode << 8); + tmpccer &= (uint16_t)(~((uint16_t)TIM_CC2P)); + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 4); + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 4); + + if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM9)|| (TIMx == TIM10)) + { + tmpccer &= (uint16_t)(~((uint16_t)TIM_CC2NP)); + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCNPolarity << 4); + tmpccer &= (uint16_t)(~((uint16_t)TIM_CC2NE)); + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputNState << 4); + + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_OIS2)); + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_OIS2N)); + tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 2); + tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCNIdleState << 2); + } + + TIMx->CTLR2 = tmpcr2; + TIMx->CHCTLR1 = tmpccmrx; + TIMx->CH2CVR = TIM_OCInitStruct->TIM_Pulse; + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_OC3Init +* Description : Initializes the TIMx Channel3 according to the specified +* parameters in the TIM_OCInitStruct. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0; + + TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CC3E)); + tmpccer = TIMx->CCER; + tmpcr2 = TIMx->CTLR2; + tmpccmrx = TIMx->CHCTLR2; + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_OC3M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CC3S)); + tmpccmrx |= TIM_OCInitStruct->TIM_OCMode; + tmpccer &= (uint16_t)(~((uint16_t)TIM_CC3P)); + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 8); + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 8); + + if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM9)|| (TIMx == TIM10)) + { + tmpccer &= (uint16_t)(~((uint16_t)TIM_CC3NP)); + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCNPolarity << 8); + tmpccer &= (uint16_t)(~((uint16_t)TIM_CC3NE)); + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputNState << 8); + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_OIS3)); + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_OIS3N)); + tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 4); + tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCNIdleState << 4); + } + + TIMx->CTLR2 = tmpcr2; + TIMx->CHCTLR2 = tmpccmrx; + TIMx->CH3CVR = TIM_OCInitStruct->TIM_Pulse; + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_OC4Init +* Description : Initializes the TIMx Channel4 according to the specified +* parameters in the TIM_OCInitStruct. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0; + + TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CC4E)); + tmpccer = TIMx->CCER; + tmpcr2 = TIMx->CTLR2; + tmpccmrx = TIMx->CHCTLR2; + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_OC4M)); + tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CC4S)); + tmpccmrx |= (uint16_t)(TIM_OCInitStruct->TIM_OCMode << 8); + tmpccer &= (uint16_t)(~((uint16_t)TIM_CC4P)); + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 12); + tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 12); + + if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM9)|| (TIMx == TIM10)) + { + tmpcr2 &= (uint16_t)(~((uint16_t)TIM_OIS4)); + tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 6); + } + + TIMx->CTLR2 = tmpcr2; + TIMx->CHCTLR2 = tmpccmrx; + TIMx->CH4CVR = TIM_OCInitStruct->TIM_Pulse; + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_ICInit +* Description : IInitializes the TIM peripheral according to the specified +* parameters in the TIM_ICInitStruct. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct) +{ + if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1) + { + TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_2) + { + TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_3) + { + TI3_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + TIM_SetIC3Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else + { + TI4_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, + TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + TIM_SetIC4Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } +} + +/******************************************************************************* +* Function Name : TIM_PWMIConfig +* Description : Configures the TIM peripheral according to the specified +* parameters in the TIM_ICInitStruct to measure an external PWM signal. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct) +{ + uint16_t icoppositepolarity = TIM_ICPolarity_Rising; + uint16_t icoppositeselection = TIM_ICSelection_DirectTI; + + if (TIM_ICInitStruct->TIM_ICPolarity == TIM_ICPolarity_Rising) + { + icoppositepolarity = TIM_ICPolarity_Falling; + } + else + { + icoppositepolarity = TIM_ICPolarity_Rising; + } + + if (TIM_ICInitStruct->TIM_ICSelection == TIM_ICSelection_DirectTI) + { + icoppositeselection = TIM_ICSelection_IndirectTI; + } + else + { + icoppositeselection = TIM_ICSelection_DirectTI; + } + + if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1) + { + TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + TI2_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter); + TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } + else + { + TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection, + TIM_ICInitStruct->TIM_ICFilter); + TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + TI1_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter); + TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler); + } +} + +/******************************************************************************* +* Function Name : TIM_BDTRConfig +* Description : Configures the: Break feature, dead time, Lock level, the OSSI, +* the OSSR State and the AOE(automatic output enable). +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_BDTRInitStruct: pointer to a TIM_BDTRInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_BDTRConfig(TIM_TypeDef* TIMx, TIM_BDTRInitTypeDef *TIM_BDTRInitStruct) +{ + TIMx->BDTR = (uint32_t)TIM_BDTRInitStruct->TIM_OSSRState | TIM_BDTRInitStruct->TIM_OSSIState | + TIM_BDTRInitStruct->TIM_LOCKLevel | TIM_BDTRInitStruct->TIM_DeadTime | + TIM_BDTRInitStruct->TIM_Break | TIM_BDTRInitStruct->TIM_BreakPolarity | + TIM_BDTRInitStruct->TIM_AutomaticOutput; +} + +/******************************************************************************* +* Function Name : TIM_TimeBaseStructInit +* Description : Fills each TIM_TimeBaseInitStruct member with its default value. +* Input : TIM_TimeBaseInitStruct : pointer to a TIM_TimeBaseInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) +{ + TIM_TimeBaseInitStruct->TIM_Period = 0xFFFF; + TIM_TimeBaseInitStruct->TIM_Prescaler = 0x0000; + TIM_TimeBaseInitStruct->TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseInitStruct->TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInitStruct->TIM_RepetitionCounter = 0x0000; +} + +/******************************************************************************* +* Function Name : TIM_OCStructInit +* Description : Fills each TIM_OCInitStruct member with its default value. +* Input : TIM_OCInitStruct : pointer to a TIM_OCInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct) +{ + TIM_OCInitStruct->TIM_OCMode = TIM_OCMode_Timing; + TIM_OCInitStruct->TIM_OutputState = TIM_OutputState_Disable; + TIM_OCInitStruct->TIM_OutputNState = TIM_OutputNState_Disable; + TIM_OCInitStruct->TIM_Pulse = 0x0000; + TIM_OCInitStruct->TIM_OCPolarity = TIM_OCPolarity_High; + TIM_OCInitStruct->TIM_OCNPolarity = TIM_OCPolarity_High; + TIM_OCInitStruct->TIM_OCIdleState = TIM_OCIdleState_Reset; + TIM_OCInitStruct->TIM_OCNIdleState = TIM_OCNIdleState_Reset; +} + +/******************************************************************************* +* Function Name : TIM_ICStructInit +* Description : Fills each TIM_ICInitStruct member with its default value. +* Input : TIM_ICInitStruct : pointer to a TIM_ICInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct) +{ + TIM_ICInitStruct->TIM_Channel = TIM_Channel_1; + TIM_ICInitStruct->TIM_ICPolarity = TIM_ICPolarity_Rising; + TIM_ICInitStruct->TIM_ICSelection = TIM_ICSelection_DirectTI; + TIM_ICInitStruct->TIM_ICPrescaler = TIM_ICPSC_DIV1; + TIM_ICInitStruct->TIM_ICFilter = 0x00; +} + +/******************************************************************************* +* Function Name : TIM_BDTRStructInit +* Description : Fills each TIM_BDTRInitStruct member with its default value. +* Input : TIM_BDTRInitStruct : pointer to a TIM_BDTRInitTypeDef structure. +* Return : None +*******************************************************************************/ +void TIM_BDTRStructInit(TIM_BDTRInitTypeDef* TIM_BDTRInitStruct) +{ + TIM_BDTRInitStruct->TIM_OSSRState = TIM_OSSRState_Disable; + TIM_BDTRInitStruct->TIM_OSSIState = TIM_OSSIState_Disable; + TIM_BDTRInitStruct->TIM_LOCKLevel = TIM_LOCKLevel_OFF; + TIM_BDTRInitStruct->TIM_DeadTime = 0x00; + TIM_BDTRInitStruct->TIM_Break = TIM_Break_Disable; + TIM_BDTRInitStruct->TIM_BreakPolarity = TIM_BreakPolarity_Low; + TIM_BDTRInitStruct->TIM_AutomaticOutput = TIM_AutomaticOutput_Disable; +} + +/******************************************************************************* +* Function Name : TIM_Cmd +* Description : Enables or disables the specified TIM peripheral. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + TIMx->CTLR1 |= TIM_CEN; + } + else + { + TIMx->CTLR1 &= (uint16_t)(~((uint16_t)TIM_CEN)); + } +} + +/******************************************************************************* +* Function Name : TIM_CtrlPWMOutputs +* Description : Enables or disables the TIM peripheral Main Outputs. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + TIMx->BDTR |= TIM_MOE; + } + else + { + TIMx->BDTR &= (uint16_t)(~((uint16_t)TIM_MOE)); + } +} + +/******************************************************************************* +* Function Name : TIM_ITConfig +* Description : Enables or disables the specified TIM interrupts. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_IT: specifies the TIM interrupts sources to be enabled or disabled. +* TIM_IT_Update: TIM update Interrupt source. +* TIM_IT_CC1: TIM Capture Compare 1 Interrupt source. +* TIM_IT_CC2: TIM Capture Compare 2 Interrupt source +* TIM_IT_CC3: TIM Capture Compare 3 Interrupt source. +* TIM_IT_CC4: TIM Capture Compare 4 Interrupt source. +* TIM_IT_COM: TIM Commutation Interrupt source. +* TIM_IT_Trigger: TIM Trigger Interrupt source. +* TIM_IT_Break: TIM Break Interrupt source. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + TIMx->DMAINTENR |= TIM_IT; + } + else + { + TIMx->DMAINTENR &= (uint16_t)~TIM_IT; + } +} + +/******************************************************************************* +* Function Name : TIM_GenerateEvent +* Description : Configures the TIMx event to be generate by software. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_EventSource: specifies the event source. +* TIM_EventSource_Update: Timer update Event source. +* TIM_EventSource_CC1: Timer Capture Compare 1 Event source. +* TIM_EventSource_CC2: Timer Capture Compare 2 Event source. +* TIM_EventSource_CC3: Timer Capture Compare 3 Event source. +* TIM_EventSource_CC4: Timer Capture Compare 4 Event source. +* TIM_EventSource_COM: Timer COM event source. +* TIM_EventSource_Trigger: Timer Trigger Event source. +* TIM_EventSource_Break: Timer Break event source. +* Return : None +*******************************************************************************/ +void TIM_GenerateEvent(TIM_TypeDef* TIMx, uint16_t TIM_EventSource) +{ + TIMx->SWEVGR = TIM_EventSource; +} + +/******************************************************************************* +* Function Name : TIM_DMAConfig +* Description : Configures the TIMx's DMA interface. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_DMABase: DMA Base address. +* TIM_DMABase_CR. +* TIM_DMABase_CR2. +* TIM_DMABase_SMCR. +* TIM_DMABase_DIER. +* TIM1_DMABase_SR. +* TIM_DMABase_EGR. +* TIM_DMABase_CCMR1. +* TIM_DMABase_CCMR2. +* TIM_DMABase_CCER. +* TIM_DMABase_CNT. +* TIM_DMABase_PSC. +* TIM_DMABase_CCR1. +* TIM_DMABase_CCR2. +* TIM_DMABase_CCR3. +* TIM_DMABase_CCR4. +* TIM_DMABase_BDTR. +* TIM_DMABase_DCR. +* TIM_DMABurstLength: DMA Burst length. +* TIM_DMABurstLength_1Transfer. +* TIM_DMABurstLength_18Transfers. +* Return : None +*******************************************************************************/ +void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength) +{ + TIMx->DMACFGR = TIM_DMABase | TIM_DMABurstLength; +} + +/******************************************************************************* +* Function Name : TIM_DMACmd +* Description : Enables or disables the TIMx's DMA Requests. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_DMASource: specifies the DMA Request sources. +* TIM_DMA_Update: TIM update Interrupt source. +* TIM_DMA_CC1: TIM Capture Compare 1 DMA source. +* TIM_DMA_CC2: TIM Capture Compare 2 DMA source. +* TIM_DMA_CC3: TIM Capture Compare 3 DMA source. +* TIM_DMA_CC4: TIM Capture Compare 4 DMA source. +* TIM_DMA_COM: TIM Commutation DMA source. +* TIM_DMA_Trigger: TIM Trigger DMA source. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + TIMx->DMAINTENR |= TIM_DMASource; + } + else + { + TIMx->DMAINTENR &= (uint16_t)~TIM_DMASource; + } +} + +/******************************************************************************* +* Function Name : TIM_InternalClockConfig +* Description : Configures the TIMx internal Clock. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* Return : None +*******************************************************************************/ +void TIM_InternalClockConfig(TIM_TypeDef* TIMx) +{ + TIMx->SMCFGR &= (uint16_t)(~((uint16_t)TIM_SMS)); +} + +/******************************************************************************* +* Function Name : TIM_ITRxExternalClockConfig +* Description : Configures the TIMx Internal Trigger as External Clock. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_InputTriggerSource: Trigger source. +* TIM_TS_ITR0: Internal Trigger 0. +* TIM_TS_ITR1: Internal Trigger 1. +* TIM_TS_ITR2: Internal Trigger 2. +* TIM_TS_ITR3: Internal Trigger 3. +* Return : None +*******************************************************************************/ +void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource) +{ + TIM_SelectInputTrigger(TIMx, TIM_InputTriggerSource); + TIMx->SMCFGR |= TIM_SlaveMode_External1; +} + +/******************************************************************************* +* Function Name : TIM_TIxExternalClockConfig +* Description : Configures the TIMx Trigger as External Clock. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_TIxExternalCLKSource: Trigger source. +* TIM_TIxExternalCLK1Source_TI1ED: TI1 Edge Detector. +* TIM_TIxExternalCLK1Source_TI1: Filtered Timer Input 1. +* TIM_TIxExternalCLK1Source_TI2: Filtered Timer Input 2. +* TIM_ICPolarity: specifies the TIx Polarity. +* TIM_ICPolarity_Rising. +* TIM_ICPolarity_Falling. +* TIM_DMA_COM: TIM Commutation DMA source. +* TIM_DMA_Trigger: TIM Trigger DMA source. +* ICFilter : specifies the filter value. +* This parameter must be a value between 0x0 and 0xF. +* Return : None +*******************************************************************************/ +void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource, + uint16_t TIM_ICPolarity, uint16_t ICFilter) +{ + if (TIM_TIxExternalCLKSource == TIM_TIxExternalCLK1Source_TI2) + { + TI2_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter); + } + else + { + TI1_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter); + } + + TIM_SelectInputTrigger(TIMx, TIM_TIxExternalCLKSource); + TIMx->SMCFGR |= TIM_SlaveMode_External1; +} + +/******************************************************************************* +* Function Name : TIM_ETRClockMode1Config +* Description : Configures the External clock Mode1. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_ExtTRGPrescaler: The external Trigger Prescaler. +* TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF. +* TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2. +* TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4. +* TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8. +* TIM_ExtTRGPolarity: The external Trigger Polarity. +* TIM_ExtTRGPolarity_Inverted: active low or falling edge active. +* TIM_ExtTRGPolarity_NonInverted: active high or rising edge active. +* ExtTRGFilter: External Trigger Filter. +* This parameter must be a value between 0x0 and 0xF. +* Return : None +*******************************************************************************/ +void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + uint16_t tmpsmcr = 0; + + TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter); + tmpsmcr = TIMx->SMCFGR; + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMS)); + tmpsmcr |= TIM_SlaveMode_External1; + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_TS)); + tmpsmcr |= TIM_TS_ETRF; + TIMx->SMCFGR = tmpsmcr; +} + +/******************************************************************************* +* Function Name : TIM_ETRClockMode2Config +* Description : Configures the External clock Mode2. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_ExtTRGPrescaler: The external Trigger Prescaler. +* TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF. +* TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2. +* TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4. +* TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8. +* TIM_ExtTRGPolarity: The external Trigger Polarity. +* TIM_ExtTRGPolarity_Inverted: active low or falling edge active. +* TIM_ExtTRGPolarity_NonInverted: active high or rising edge active. +* ExtTRGFilter: External Trigger Filter. +* This parameter must be a value between 0x0 and 0xF. +* Return : None +*******************************************************************************/ +void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, + uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter) +{ + TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter); + TIMx->SMCFGR |= TIM_ECE; +} + +/******************************************************************************* +* Function Name : TIM_ETRConfig +* Description : Configures the TIMx External Trigger (ETR). +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_ExtTRGPrescaler: The external Trigger Prescaler. +* TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF. +* TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2. +* TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4. +* TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8. +* TIM_ExtTRGPolarity: The external Trigger Polarity. +* TIM_ExtTRGPolarity_Inverted: active low or falling edge active. +* TIM_ExtTRGPolarity_NonInverted: active high or rising edge active. +* ExtTRGFilter: External Trigger Filter. +* This parameter must be a value between 0x0 and 0xF. +* Return : None +*******************************************************************************/ +void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, + uint16_t ExtTRGFilter) +{ + uint16_t tmpsmcr = 0; + + tmpsmcr = TIMx->SMCFGR; + tmpsmcr &= SMCFGR_ETR_Mask; + tmpsmcr |= (uint16_t)(TIM_ExtTRGPrescaler | (uint16_t)(TIM_ExtTRGPolarity | (uint16_t)(ExtTRGFilter << (uint16_t)8))); + TIMx->SMCFGR = tmpsmcr; +} + +/******************************************************************************* +* Function Name : TIM_PrescalerConfig +* Description : Configures the TIMx Prescaler. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* Prescaler: specifies the Prescaler Register value. +* TIM_PSCReloadMode: specifies the TIM Prescaler Reload mode. +* TIM_PSCReloadMode: specifies the TIM Prescaler Reload mode. +* TIM_PSCReloadMode_Update: The Prescaler is loaded at the update event. +* TIM_PSCReloadMode_Immediate: The Prescaler is loaded immediately. +* Return : None +*******************************************************************************/ +void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode) +{ + TIMx->PSC = Prescaler; + TIMx->SWEVGR = TIM_PSCReloadMode; +} + +/******************************************************************************* +* Function Name : TIM_CounterModeConfig +* Description : Specifies the TIMx Counter Mode to be used. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_CounterMode: specifies the Counter Mode to be used. +* TIM_CounterMode_Up: TIM Up Counting Mode. +* TIM_CounterMode_Down: TIM Down Counting Mode. +* TIM_CounterMode_CenterAligned1: TIM Center Aligned Mode1. +* TIM_CounterMode_CenterAligned2: TIM Center Aligned Mode2. +* TIM_CounterMode_CenterAligned3: TIM Center Aligned Mode3. +* Return : None +*******************************************************************************/ +void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode) +{ + uint16_t tmpcr1 = 0; + + tmpcr1 = TIMx->CTLR1; + tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_DIR | TIM_CMS))); + tmpcr1 |= TIM_CounterMode; + TIMx->CTLR1 = tmpcr1; +} + +/******************************************************************************* +* Function Name : TIM_SelectInputTrigger +* Description : Selects the Input Trigger source. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_InputTriggerSource: The Input Trigger source. +* TIM_TS_ITR0: Internal Trigger 0. +* TIM_TS_ITR1: Internal Trigger 1. +* TIM_TS_ITR2: Internal Trigger 2. +* TIM_TS_ITR3: Internal Trigger 3. +* TIM_TS_TI1F_ED: TI1 Edge Detector. +* TIM_TS_TI1FP1: Filtered Timer Input 1. +* TIM_TS_TI2FP2: Filtered Timer Input 2. +* TIM_TS_ETRF: External Trigger input. +* Return : None +*******************************************************************************/ +void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource) +{ + uint16_t tmpsmcr = 0; + + tmpsmcr = TIMx->SMCFGR; + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_TS)); + tmpsmcr |= TIM_InputTriggerSource; + TIMx->SMCFGR = tmpsmcr; +} + +/******************************************************************************* +* Function Name : TIM_EncoderInterfaceConfig +* Description : Configures the TIMx Encoder Interface. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_EncoderMode: specifies the TIMx Encoder Mode. +* TIM_EncoderMode_TI1: Counter counts on TI1FP1 edge depending +* on TI2FP2 level. +* TIM_EncoderMode_TI2: Counter counts on TI2FP2 edge depending +* on TI1FP1 level. +* TIM_EncoderMode_TI12: Counter counts on both TI1FP1 and +* TI2FP2 edges depending. +* TIM_IC1Polarity: specifies the IC1 Polarity. +* TIM_ICPolarity_Falling: IC Falling edge. +* TTIM_ICPolarity_Rising: IC Rising edge. +* TIM_IC2Polarity: specifies the IC2 Polarity. +* TIM_ICPolarity_Falling: IC Falling edge. +* TIM_ICPolarity_Rising: IC Rising edge. +* Return : None +*******************************************************************************/ +void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode, + uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity) +{ + uint16_t tmpsmcr = 0; + uint16_t tmpccmr1 = 0; + uint16_t tmpccer = 0; + + tmpsmcr = TIMx->SMCFGR; + tmpccmr1 = TIMx->CHCTLR1; + tmpccer = TIMx->CCER; + tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMS)); + tmpsmcr |= TIM_EncoderMode; + tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CC1S)) & (uint16_t)(~((uint16_t)TIM_CC2S))); + tmpccmr1 |= TIM_CC1S_0 | TIM_CC2S_0; + tmpccer &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CC1P)) & ((uint16_t)~((uint16_t)TIM_CC2P))); + tmpccer |= (uint16_t)(TIM_IC1Polarity | (uint16_t)(TIM_IC2Polarity << (uint16_t)4)); + TIMx->SMCFGR = tmpsmcr; + TIMx->CHCTLR1 = tmpccmr1; + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_ForcedOC1Config +* Description : Forces the TIMx output 1 waveform to active or inactive level. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_ForcedAction: specifies the forced Action to be set to the +* output waveform. +* TIM_ForcedAction_Active: Force active level on OC1REF. +* TIM_ForcedAction_InActive: Force inactive level on OC1REF. +* Return : None +*******************************************************************************/ +void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr1 = 0; + + tmpccmr1 = TIMx->CHCTLR1; + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_OC1M); + tmpccmr1 |= TIM_ForcedAction; + TIMx->CHCTLR1 = tmpccmr1; +} + +/******************************************************************************* +* Function Name : TIM_ForcedOC2Config +* Description : Forces the TIMx output 2 waveform to active or inactive level. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_ForcedAction: specifies the forced Action to be set to the +* output waveform. +* TIM_ForcedAction_Active: Force active level on OC2REF. +* TIM_ForcedAction_InActive: Force inactive level on OC2REF. +* Return : None +*******************************************************************************/ +void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr1 = 0; + + tmpccmr1 = TIMx->CHCTLR1; + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_OC2M); + tmpccmr1 |= (uint16_t)(TIM_ForcedAction << 8); + TIMx->CHCTLR1 = tmpccmr1; +} + +/******************************************************************************* +* Function Name : TIM_ForcedOC3Config +* Description : Forces the TIMx output 3 waveform to active or inactive level. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_ForcedAction: specifies the forced Action to be set to the +* output waveform. +* TIM_ForcedAction_Active: Force active level on OC3REF. +* TIM_ForcedAction_InActive: Force inactive level on OC3REF. +* Return : None +*******************************************************************************/ +void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr2 = 0; + + tmpccmr2 = TIMx->CHCTLR2; + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_OC3M); + tmpccmr2 |= TIM_ForcedAction; + TIMx->CHCTLR2 = tmpccmr2; +} + +/******************************************************************************* +* Function Name : TIM_ForcedOC4Config +* Description : Forces the TIMx output 4 waveform to active or inactive level. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_ForcedAction: specifies the forced Action to be set to the +* output waveform. +* TIM_ForcedAction_Active: Force active level on OC4REF. +* TIM_ForcedAction_InActive: Force inactive level on OC4REF. +* Return : None +*******************************************************************************/ +void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction) +{ + uint16_t tmpccmr2 = 0; + + tmpccmr2 = TIMx->CHCTLR2; + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_OC4M); + tmpccmr2 |= (uint16_t)(TIM_ForcedAction << 8); + TIMx->CHCTLR2 = tmpccmr2; +} + +/******************************************************************************* +* Function Name : TIM_ARRPreloadConfig +* Description : Enables or disables TIMx peripheral Preload register on ARR. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + TIMx->CTLR1 |= TIM_ARPE; + } + else + { + TIMx->CTLR1 &= (uint16_t)~((uint16_t)TIM_ARPE); + } +} + +/******************************************************************************* +* Function Name : TIM_SelectCOM +* Description : Selects the TIM peripheral Commutation event. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void TIM_SelectCOM(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + TIMx->CTLR2 |= TIM_CCUS; + } + else + { + TIMx->CTLR2 &= (uint16_t)~((uint16_t)TIM_CCUS); + } +} + +/******************************************************************************* +* Function Name : TIM_SelectCCDMA +* Description : Selects the TIMx peripheral Capture Compare DMA source. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void TIM_SelectCCDMA(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + TIMx->CTLR2 |= TIM_CCDS; + } + else + { + TIMx->CTLR2 &= (uint16_t)~((uint16_t)TIM_CCDS); + } +} + +/******************************************************************************* +* Function Name : TIM_CCPreloadControl +* Description : Sets or Resets the TIM peripheral Capture Compare Preload Control bit. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void TIM_CCPreloadControl(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + TIMx->CTLR2 |= TIM_CCPC; + } + else + { + TIMx->CTLR2 &= (uint16_t)~((uint16_t)TIM_CCPC); + } +} + +/******************************************************************************* +* Function Name : TIM_OC1PreloadConfig +* Description : Enables or disables the TIMx peripheral Preload register on CCR1. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCPreload: new state of the TIMx peripheral Preload register. +* TIM_OCPreload_Enable. +* TIM_OCPreload_Disable. +* Return : None +*******************************************************************************/ +void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr1 = 0; + + tmpccmr1 = TIMx->CHCTLR1; + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_OC1PE); + tmpccmr1 |= TIM_OCPreload; + TIMx->CHCTLR1 = tmpccmr1; +} + +/******************************************************************************* +* Function Name : TIM_OC2PreloadConfig +* Description : Enables or disables the TIMx peripheral Preload register on CCR2. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCPreload: new state of the TIMx peripheral Preload register. +* TIM_OCPreload_Enable. +* TIM_OCPreload_Disable. +* Return : None +*******************************************************************************/ +void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr1 = 0; + + tmpccmr1 = TIMx->CHCTLR1; + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_OC2PE); + tmpccmr1 |= (uint16_t)(TIM_OCPreload << 8); + TIMx->CHCTLR1 = tmpccmr1; +} + +/******************************************************************************* +* Function Name : TIM_OC3PreloadConfig +* Description : Enables or disables the TIMx peripheral Preload register on CCR3. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCPreload: new state of the TIMx peripheral Preload register. +* TIM_OCPreload_Enable. +* TIM_OCPreload_Disable. +* Return : None +*******************************************************************************/ +void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr2 = 0; + + tmpccmr2 = TIMx->CHCTLR2; + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_OC3PE); + tmpccmr2 |= TIM_OCPreload; + TIMx->CHCTLR2 = tmpccmr2; +} + +/******************************************************************************* +* Function Name : TIM_OC4PreloadConfig +* Description : Enables or disables the TIMx peripheral Preload register on CCR4. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCPreload: new state of the TIMx peripheral Preload register. +* TIM_OCPreload_Enable. +* TIM_OCPreload_Disable. +* Return : None +*******************************************************************************/ +void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload) +{ + uint16_t tmpccmr2 = 0; + + tmpccmr2 = TIMx->CHCTLR2; + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_OC4PE); + tmpccmr2 |= (uint16_t)(TIM_OCPreload << 8); + TIMx->CHCTLR2 = tmpccmr2; +} + +/******************************************************************************* +* Function Name : TIM_OC1FastConfig +* Description : Configures the TIMx Output Compare 1 Fast feature. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCFast: new state of the Output Compare Fast Enable Bit. +* TIM_OCFast_Enable: TIM output compare fast enable. +* TIM_OCFast_Disable: TIM output compare fast disable. +* Return : None +*******************************************************************************/ +void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr1 = 0; + + tmpccmr1 = TIMx->CHCTLR1; + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_OC1FE); + tmpccmr1 |= TIM_OCFast; + TIMx->CHCTLR1 = tmpccmr1; +} + +/******************************************************************************* +* Function Name : TIM_OC2FastConfig +* Description : Configures the TIMx Output Compare 2 Fast feature. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCFast: new state of the Output Compare Fast Enable Bit. +* TIM_OCFast_Enable: TIM output compare fast enable. +* TIM_OCFast_Disable: TIM output compare fast disable. +* Return : None +*******************************************************************************/ +void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr1 = 0; + + tmpccmr1 = TIMx->CHCTLR1; + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_OC2FE); + tmpccmr1 |= (uint16_t)(TIM_OCFast << 8); + TIMx->CHCTLR1 = tmpccmr1; +} + +/******************************************************************************* +* Function Name : TIM_OC3FastConfig +* Description : Configures the TIMx Output Compare 3 Fast feature. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCFast: new state of the Output Compare Fast Enable Bit. +* TIM_OCFast_Enable: TIM output compare fast enable. +* TIM_OCFast_Disable: TIM output compare fast disable. +* Return : None +*******************************************************************************/ +void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr2 = 0; + + tmpccmr2 = TIMx->CHCTLR2; + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_OC3FE); + tmpccmr2 |= TIM_OCFast; + TIMx->CHCTLR2 = tmpccmr2; +} + +/******************************************************************************* +* Function Name : TIM_OC4FastConfig +* Description : Configures the TIMx Output Compare 4 Fast feature. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCFast: new state of the Output Compare Fast Enable Bit. +* TIM_OCFast_Enable: TIM output compare fast enable. +* TIM_OCFast_Disable: TIM output compare fast disable. +* Return : None +*******************************************************************************/ +void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast) +{ + uint16_t tmpccmr2 = 0; + + tmpccmr2 = TIMx->CHCTLR2; + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_OC4FE); + tmpccmr2 |= (uint16_t)(TIM_OCFast << 8); + TIMx->CHCTLR2 = tmpccmr2; +} + +/******************************************************************************* +* Function Name : TIM_ClearOC1Ref +* Description : Clears or safeguards the OCREF1 signal on an external event. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCClear: new state of the Output Compare Clear Enable Bit. +* TIM_OCClear_Enable: TIM Output clear enable. +* TIM_OCClear_Disable: TIM Output clear disable. +* Return : None +*******************************************************************************/ +void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr1 = 0; + + tmpccmr1 = TIMx->CHCTLR1; + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_OC1CE); + tmpccmr1 |= TIM_OCClear; + TIMx->CHCTLR1 = tmpccmr1; +} + +/******************************************************************************* +* Function Name : TIM_ClearOC2Ref +* Description : Clears or safeguards the OCREF2 signal on an external event. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCClear: new state of the Output Compare Clear Enable Bit. +* TIM_OCClear_Enable: TIM Output clear enable. +* TIM_OCClear_Disable: TIM Output clear disable. +* Return : None +*******************************************************************************/ +void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr1 = 0; + + tmpccmr1 = TIMx->CHCTLR1; + tmpccmr1 &= (uint16_t)~((uint16_t)TIM_OC2CE); + tmpccmr1 |= (uint16_t)(TIM_OCClear << 8); + TIMx->CHCTLR1 = tmpccmr1; +} + +/******************************************************************************* +* Function Name : TIM_ClearOC3Ref +* Description : Clears or safeguards the OCREF3 signal on an external event. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCClear: new state of the Output Compare Clear Enable Bit. +* TIM_OCClear_Enable: TIM Output clear enable. +* TIM_OCClear_Disable: TIM Output clear disable. +* Return : None +*******************************************************************************/ +void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr2 = 0; + + tmpccmr2 = TIMx->CHCTLR2; + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_OC3CE); + tmpccmr2 |= TIM_OCClear; + TIMx->CHCTLR2 = tmpccmr2; +} + +/******************************************************************************* +* Function Name : TIM_ClearOC4Ref +* Description : Clears or safeguards the OCREF4 signal on an external event. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCClear: new state of the Output Compare Clear Enable Bit. +* TIM_OCClear_Enable: TIM Output clear enable. +* TIM_OCClear_Disable: TIM Output clear disable. +* Return : None +*******************************************************************************/ +void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear) +{ + uint16_t tmpccmr2 = 0; + + tmpccmr2 = TIMx->CHCTLR2; + tmpccmr2 &= (uint16_t)~((uint16_t)TIM_OC4CE); + tmpccmr2 |= (uint16_t)(TIM_OCClear << 8); + TIMx->CHCTLR2 = tmpccmr2; +} + +/******************************************************************************* +* Function Name : TIM_OC1PolarityConfig +* Description : Configures the TIMx channel 1 polarity. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCPolarity: specifies the OC1 Polarity. +* TIM_OCPolarity_High: Output Compare active high. +* TIM_OCPolarity_Low: Output Compare active low. +* Return : None +*******************************************************************************/ +void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + + tmpccer = TIMx->CCER; + tmpccer &= (uint16_t)~((uint16_t)TIM_CC1P); + tmpccer |= TIM_OCPolarity; + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_OC1NPolarityConfig +* Description : Configures the TIMx channel 1 polarity. +* Input : TIMx: where x can be 1 to select the TIM peripheral. +* TIM_OCNPolarity: specifies the OC1N Polarity. +* TIM_OCNPolarity_High: Output Compare active high. +* TIM_OCNPolarity_Low: Output Compare active low. +* Return : None +*******************************************************************************/ +void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity) +{ + uint16_t tmpccer = 0; + + tmpccer = TIMx->CCER; + tmpccer &= (uint16_t)~((uint16_t)TIM_CC1NP); + tmpccer |= TIM_OCNPolarity; + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_OC2PolarityConfig +* Description : Configures the TIMx channel 2 polarity. +* Input : TIMx: where x can be 1 to 4 to select the TIM peripheral. +* TIM_OCPolarity: specifies the OC2 Polarity. +* TIM_OCPolarity_High: Output Compare active high. +* TIM_OCPolarity_Low: Output Compare active low. +* Return : None +*******************************************************************************/ +void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + + tmpccer = TIMx->CCER; + tmpccer &= (uint16_t)~((uint16_t)TIM_CC2P); + tmpccer |= (uint16_t)(TIM_OCPolarity << 4); + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_OC2NPolarityConfig +* Description : Configures the TIMx Channel 2N polarity. +* Input : TIMx: where x can be 1 to select the TIM peripheral. +* TIM_OCNPolarity: specifies the OC2N Polarity. +* TIM_OCNPolarity_High: Output Compare active high. +* TIM_OCNPolarity_Low: Output Compare active low. +* Return : None +*******************************************************************************/ +void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity) +{ + uint16_t tmpccer = 0; + + tmpccer = TIMx->CCER; + tmpccer &= (uint16_t)~((uint16_t)TIM_CC2NP); + tmpccer |= (uint16_t)(TIM_OCNPolarity << 4); + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_OC3PolarityConfig +* Description : Configures the TIMx Channel 3 polarity. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_OCPolarity: specifies the OC3 Polarity. +* TIM_OCPolarity_High: Output Compare active high. +* TIM_OCPolarity_Low: Output Compare active low. +* Return : None +*******************************************************************************/ +void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + + tmpccer = TIMx->CCER; + tmpccer &= (uint16_t)~((uint16_t)TIM_CC3P); + tmpccer |= (uint16_t)(TIM_OCPolarity << 8); + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_OC3NPolarityConfig +* Description : Configures the TIMx Channel 3N polarity. +* Input : TIMx: where x can be 1 to select the TIM peripheral. +* TIM_OCNPolarity: specifies the OC2N Polarity. +* TIM_OCNPolarity_High: Output Compare active high. +* TIM_OCNPolarity_Low: Output Compare active low. +* Return : None +*******************************************************************************/ +void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity) +{ + uint16_t tmpccer = 0; + + tmpccer = TIMx->CCER; + tmpccer &= (uint16_t)~((uint16_t)TIM_CC3NP); + tmpccer |= (uint16_t)(TIM_OCNPolarity << 8); + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_OC4PolarityConfig +* Description : Configures the TIMx channel 4 polarity. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_OCPolarity: specifies the OC4 Polarity. +* TIM_OCPolarity_High: Output Compare active high. +* TIM_OCPolarity_Low: Output Compare active low. +* Return : None +*******************************************************************************/ +void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity) +{ + uint16_t tmpccer = 0; + + tmpccer = TIMx->CCER; + tmpccer &= (uint16_t)~((uint16_t)TIM_CC4P); + tmpccer |= (uint16_t)(TIM_OCPolarity << 12); + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TIM_CCxCmd +* Description : Enables or disables the TIM Capture Compare Channel x. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_Channel: specifies the TIM Channel. +* TIM_Channel_1: TIM Channel 1. +* TIM_Channel_2: TIM Channel 2. +* TIM_Channel_3: TIM Channel 3. +* TIM_Channel_4: TIM Channel 4. +* TIM_CCx: specifies the TIM Channel CCxE bit new state. +* TIM_CCx_Enable. +* TIM_CCx_Disable. +* Return : None +*******************************************************************************/ +void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx) +{ + uint16_t tmp = 0; + + tmp = CCER_CCE_Set << TIM_Channel; + TIMx->CCER &= (uint16_t)~ tmp; + TIMx->CCER |= (uint16_t)(TIM_CCx << TIM_Channel); +} + +/******************************************************************************* +* Function Name : TIM_CCxNCmd +* Description : Enables or disables the TIM Capture Compare Channel xN. +* Input : TIMx: where x can be 1 select the TIM peripheral. +* TIM_Channel: specifies the TIM Channel. +* TIM_Channel_1: TIM Channel 1. +* TIM_Channel_2: TIM Channel 2. +* TIM_Channel_3: TIM Channel 3. +* TIM_CCxN: specifies the TIM Channel CCxNE bit new state. +* TIM_CCxN_Enable. +* TIM_CCxN_Disable. +* Return : None +*******************************************************************************/ +void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN) +{ + uint16_t tmp = 0; + + tmp = CCER_CCNE_Set << TIM_Channel; + TIMx->CCER &= (uint16_t) ~tmp; + TIMx->CCER |= (uint16_t)(TIM_CCxN << TIM_Channel); +} + +/******************************************************************************* +* Function Name : TIM_SelectOCxM +* Description : Selects the TIM Output Compare Mode. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_Channel: specifies the TIM Channel. +* TIM_Channel_1: TIM Channel 1. +* TIM_Channel_2: TIM Channel 2. +* TIM_Channel_3: TIM Channel 3. +* TIM_Channel_4: TIM Channel 4. +* TIM_OCMode: specifies the TIM Output Compare Mode. +* TIM_OCMode_Timing. +* TIM_OCMode_Active. +* TIM_OCMode_Toggle. +* TIM_OCMode_PWM1. +* TIM_OCMode_PWM2. +* TIM_ForcedAction_Active. +* TIM_ForcedAction_InActive. +* Return : None +*******************************************************************************/ +void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode) +{ + uint32_t tmp = 0; + uint16_t tmp1 = 0; + + tmp = (uint32_t) TIMx; + tmp += CHCTLR_Offset; + tmp1 = CCER_CCE_Set << (uint16_t)TIM_Channel; + TIMx->CCER &= (uint16_t) ~tmp1; + + if((TIM_Channel == TIM_Channel_1) ||(TIM_Channel == TIM_Channel_3)) + { + tmp += (TIM_Channel>>1); + *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_OC1M); + *(__IO uint32_t *) tmp |= TIM_OCMode; + } + else + { + tmp += (uint16_t)(TIM_Channel - (uint16_t)4)>> (uint16_t)1; + *(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_OC2M); + *(__IO uint32_t *) tmp |= (uint16_t)(TIM_OCMode << 8); + } +} + +/******************************************************************************* +* Function Name : TIM_UpdateDisableConfig +* Description : Enables or Disables the TIMx Update event. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void TIM_UpdateDisableConfig(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + TIMx->CTLR1 |= TIM_UDIS; + } + else + { + TIMx->CTLR1 &= (uint16_t)~((uint16_t)TIM_UDIS); + } +} + +/******************************************************************************* +* Function Name : TIM_UpdateRequestConfig +* Description : Configures the TIMx Update Request Interrupt source. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_UpdateSource: specifies the Update source. +* TIM_UpdateSource_Regular. +* TIM_UpdateSource_Global. +* Return : None +*******************************************************************************/ +void TIM_UpdateRequestConfig(TIM_TypeDef* TIMx, uint16_t TIM_UpdateSource) +{ + if (TIM_UpdateSource != TIM_UpdateSource_Global) + { + TIMx->CTLR1 |= TIM_URS; + } + else + { + TIMx->CTLR1 &= (uint16_t)~((uint16_t)TIM_URS); + } +} + +/******************************************************************************* +* Function Name : TIM_SelectHallSensor +* Description : Enables or disables the TIMx's Hall sensor interface. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ +void TIM_SelectHallSensor(TIM_TypeDef* TIMx, FunctionalState NewState) +{ + if (NewState != DISABLE) + { + TIMx->CTLR2 |= TIM_TI1S; + } + else + { + TIMx->CTLR2 &= (uint16_t)~((uint16_t)TIM_TI1S); + } +} + +/******************************************************************************* +* Function Name : TIM_SelectOnePulseMode +* Description : Selects the TIMx's One Pulse Mode. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_OPMode: specifies the OPM Mode to be used. +* TIM_OPMode_Single. +* TIM_OPMode_Repetitive. +* Return : None +*******************************************************************************/ +void TIM_SelectOnePulseMode(TIM_TypeDef* TIMx, uint16_t TIM_OPMode) +{ + TIMx->CTLR1 &= (uint16_t)~((uint16_t)TIM_OPM); + TIMx->CTLR1 |= TIM_OPMode; +} + +/******************************************************************************* +* Function Name : TIM_SelectOutputTrigger +* Description : Selects the TIMx Trigger Output Mode. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_TRGOSource: specifies the Trigger Output source. +* TIM_TRGOSource_Reset: The UG bit in the TIM_EGR register is +* used as the trigger output (TRGO). +* TIM_TRGOSource_Enable: The Counter Enable CEN is used as the +* trigger output (TRGO). +* TIM_TRGOSource_Update: The update event is selected as the +* trigger output (TRGO). +* TIM_TRGOSource_OC1: The trigger output sends a positive pulse +* when the CC1IF flag is to be set, as soon as a capture or compare match occurs (TRGO). +* TIM_TRGOSource_OC1Ref: OC1REF signal is used as the trigger output (TRGO). +* TIM_TRGOSource_OC2Ref: OC2REF signal is used as the trigger output (TRGO). +* TIM_TRGOSource_OC3Ref: OC3REF signal is used as the trigger output (TRGO). +* TIM_TRGOSource_OC4Ref: OC4REF signal is used as the trigger output (TRGO). +* Return : None +*******************************************************************************/ +void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource) +{ + TIMx->CTLR2 &= (uint16_t)~((uint16_t)TIM_MMS); + TIMx->CTLR2 |= TIM_TRGOSource; +} + +/******************************************************************************* +* Function Name : TIM_SelectSlaveMode +* Description : Selects the TIMx Slave Mode. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_SlaveMode: specifies the Timer Slave Mode. +* TIM_SlaveMode_Reset: Rising edge of the selected trigger +* signal (TRGI) re-initializes. +* TIM_SlaveMode_Gated: The counter clock is enabled when the +* trigger signal (TRGI) is high. +* TIM_SlaveMode_Trigger: The counter starts at a rising edge +* of the trigger TRGI. +* TIM_SlaveMode_External1: Rising edges of the selected trigger +* (TRGI) clock the counter. +* Return : None +*******************************************************************************/ +void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode) +{ + TIMx->SMCFGR &= (uint16_t)~((uint16_t)TIM_SMS); + TIMx->SMCFGR |= TIM_SlaveMode; +} + +/******************************************************************************* +* Function Name : TIM_SelectMasterSlaveMode +* Description : Sets or Resets the TIMx Master/Slave Mode. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_MasterSlaveMode: specifies the Timer Master Slave Mode. +* TIM_MasterSlaveMode_Enable: synchronization between the current +* timer and its slaves (through TRGO). +* TIM_MasterSlaveMode_Disable: No action. +* Return : None +*******************************************************************************/ +void TIM_SelectMasterSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_MasterSlaveMode) +{ + TIMx->SMCFGR &= (uint16_t)~((uint16_t)TIM_MSM); + TIMx->SMCFGR |= TIM_MasterSlaveMode; +} + +/******************************************************************************* +* Function Name : TIM_SetCounter +* Description : Sets the TIMx Counter Register value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Counter: specifies the Counter register new value. +* Return : None +*******************************************************************************/ +void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter) +{ + TIMx->CNT = Counter; +} + +/******************************************************************************* +* Function Name : TIM_SetAutoreload +* Description : Sets the TIMx Autoreload Register value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Autoreload: specifies the Autoreload register new value. +* Return : None +*******************************************************************************/ +void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload) +{ + TIMx->ATRLR = Autoreload; +} + +/******************************************************************************* +* Function Name : TIM_SetCompare1 +* Description : Sets the TIMx Capture Compare1 Register value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Compare1: specifies the Capture Compare1 register new value. +* Return : None +*******************************************************************************/ +void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1) +{ + TIMx->CH1CVR = Compare1; +} + +/******************************************************************************* +* Function Name : TIM_SetCompare2 +* Description : Sets the TIMx Capture Compare2 Register value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Compare2: specifies the Capture Compare2 register new value. +* Return : None +*******************************************************************************/ +void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2) +{ + TIMx->CH2CVR = Compare2; +} + +/******************************************************************************* +* Function Name : TIM_SetCompare3 +* Description : Sets the TIMx Capture Compare3 Register value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Compare3: specifies the Capture Compare3 register new value. +* Return : None +*******************************************************************************/ +void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3) +{ + TIMx->CH3CVR = Compare3; +} + +/******************************************************************************* +* Function Name : TIM_SetCompare4 +* Description : Sets the TIMx Capture Compare4 Register value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Compare4: specifies the Capture Compare4 register new value. +* Return : None +*******************************************************************************/ +void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4) +{ + TIMx->CH4CVR = Compare4; +} + +/******************************************************************************* +* Function Name : TIM_SetIC1Prescaler +* Description : Sets the TIMx Input Capture 1 prescaler. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_ICPSC: specifies the Input Capture1 prescaler new value. +* TIM_ICPSC_DIV1: no prescaler. +* TIM_ICPSC_DIV2: capture is done once every 2 events. +* TIM_ICPSC_DIV4: capture is done once every 4 events. +* TIM_ICPSC_DIV8: capture is done once every 8 events. +* Return : None +*******************************************************************************/ +void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + TIMx->CHCTLR1 &= (uint16_t)~((uint16_t)TIM_IC1PSC); + TIMx->CHCTLR1 |= TIM_ICPSC; +} + +/******************************************************************************* +* Function Name : TIM_SetIC2Prescaler +* Description : Sets the TIMx Input Capture 2 prescaler. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_ICPSC: specifies the Input Capture1 prescaler new value. +* TIM_ICPSC_DIV1: no prescaler. +* TIM_ICPSC_DIV2: capture is done once every 2 events. +* TIM_ICPSC_DIV4: capture is done once every 4 events. +* TIM_ICPSC_DIV8: capture is done once every 8 events. +* Return : None +*******************************************************************************/ +void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + TIMx->CHCTLR1 &= (uint16_t)~((uint16_t)TIM_IC2PSC); + TIMx->CHCTLR1 |= (uint16_t)(TIM_ICPSC << 8); +} + +/******************************************************************************* +* Function Name : TIM_SetIC3Prescaler +* Description : Sets the TIMx Input Capture 3 prescaler. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_ICPSC: specifies the Input Capture1 prescaler new value. +* TIM_ICPSC_DIV1: no prescaler. +* TIM_ICPSC_DIV2: capture is done once every 2 events. +* TIM_ICPSC_DIV4: capture is done once every 4 events. +* TIM_ICPSC_DIV8: capture is done once every 8 events. +* Return : None +*******************************************************************************/ +void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + TIMx->CHCTLR2 &= (uint16_t)~((uint16_t)TIM_IC3PSC); + TIMx->CHCTLR2 |= TIM_ICPSC; +} + +/******************************************************************************* +* Function Name : TIM_SetIC4Prescaler +* Description : Sets the TIMx Input Capture 4 prescaler. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_ICPSC: specifies the Input Capture1 prescaler new value. +* TIM_ICPSC_DIV1: no prescaler. +* TIM_ICPSC_DIV2: capture is done once every 2 events. +* TIM_ICPSC_DIV4: capture is done once every 4 events. +* TIM_ICPSC_DIV8: capture is done once every 8 events. +* Return : None +*******************************************************************************/ +void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC) +{ + TIMx->CHCTLR2 &= (uint16_t)~((uint16_t)TIM_IC4PSC); + TIMx->CHCTLR2 |= (uint16_t)(TIM_ICPSC << 8); +} + +/******************************************************************************* +* Function Name : TIM_SetClockDivision +* Description : Sets the TIMx Clock Division value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_CKD: specifies the clock division value. +* TIM_CKD_DIV1: TDTS = Tck_tim. +* TIM_CKD_DIV2: TDTS = 2*Tck_tim. +* TIM_CKD_DIV4: TDTS = 4*Tck_tim. +* Return : None +*******************************************************************************/ +void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD) +{ + TIMx->CTLR1 &= (uint16_t)~((uint16_t)TIM_CTLR1_CKD); + TIMx->CTLR1 |= TIM_CKD; +} + +/******************************************************************************* +* Function Name : TIM_GetCapture1 +* Description : Gets the TIMx Input Capture 1 value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Return : TIMx->CH1CVR: Capture Compare 1 Register value. +*******************************************************************************/ +uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx) +{ + return TIMx->CH1CVR; +} + +/******************************************************************************* +* Function Name : TIM_GetCapture2 +* Description : Gets the TIMx Input Capture 1 value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Return : TIMx->CH2CVR: Capture Compare 2 Register value. +*******************************************************************************/ +uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx) +{ + return TIMx->CH2CVR; +} + +/******************************************************************************* +* Function Name : TIM_GetCapture3 +* Description : Gets the TIMx Input Capture 1 value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Return : TIMx->CH3CVR: Capture Compare 3 Register value. +*******************************************************************************/ +uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx) +{ + return TIMx->CH3CVR; +} + +/******************************************************************************* +* Function Name : TIM_GetCapture4 +* Description : Gets the TIMx Input Capture 1 value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Return : TIMx->CH4CVR: Capture Compare 4 Register value. +*******************************************************************************/ +uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx) +{ + return TIMx->CH4CVR; +} + +/******************************************************************************* +* Function Name : TIM_GetCounter +* Description : Gets the TIMx Counter value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Return : TIMx->CNT: Counter Register value. +*******************************************************************************/ +uint16_t TIM_GetCounter(TIM_TypeDef* TIMx) +{ + return TIMx->CNT; +} + +/******************************************************************************* +* Function Name : TIM_GetPrescaler +* Description : Gets the TIMx Prescaler value. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* Return : TIMx->PSC: Prescaler Register value. +*******************************************************************************/ +uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx) +{ + return TIMx->PSC; +} + +/******************************************************************************* +* Function Name : TIM_GetFlagStatus +* Description : Checks whether the specified TIM flag is set or not. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_FLAG: specifies the flag to check. +* TIM_FLAG_Update: TIM update Flag. +* TIM_FLAG_CC1: TIM Capture Compare 1 Flag. +* TIM_FLAG_CC2: TIM Capture Compare 2 Flag. +* TIM_FLAG_CC3: TIM Capture Compare 3 Flag. +* TIM_FLAG_CC4: TIM Capture Compare 4 Flag. +* TIM_FLAG_COM: TIM Commutation Flag. +* TIM_FLAG_Trigger: TIM Trigger Flag. +* TIM_FLAG_Break: TIM Break Flag. +* TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag. +* TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag. +* TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag. +* TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag. +* Return : bitstatus: SET or RESET. +*******************************************************************************/ +FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG) +{ + ITStatus bitstatus = RESET; + + if ((TIMx->INTFR & TIM_FLAG) != (uint16_t)RESET) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : TIM_ClearFlag +* Description : Clears the TIMx's pending flags. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_FLAG: specifies the flag bit to clear. +* TIM_FLAG_Update: TIM update Flag. +* TIM_FLAG_CC1: TIM Capture Compare 1 Flag. +* TIM_FLAG_CC2: TIM Capture Compare 2 Flag. +* TIM_FLAG_CC3: TIM Capture Compare 3 Flag. +* TIM_FLAG_CC4: TIM Capture Compare 4 Flag. +* TIM_FLAG_COM: TIM Commutation Flag. +* TIM_FLAG_Trigger: TIM Trigger Flag. +* TIM_FLAG_Break: TIM Break Flag. +* TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag. +* TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag. +* TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag. +* TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag. +* Return : None +*******************************************************************************/ +void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG) +{ + TIMx->INTFR = (uint16_t)~TIM_FLAG; +} + +/******************************************************************************* +* Function Name : TIM_GetITStatus +* Description : Checks whether the TIM interrupt has occurred or not. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_IT: specifies the TIM interrupt source to check. +* TIM_IT_Update: TIM update Interrupt source. +* TIM_IT_CC1: TIM Capture Compare 1 Interrupt source. +* TIM_IT_CC2: TIM Capture Compare 2 Interrupt source. +* TIM_IT_CC3: TIM Capture Compare 3 Interrupt source. +* TIM_IT_CC4: TIM Capture Compare 4 Interrupt source. +* TIM_IT_COM: TIM Commutation Interrupt source. +* TIM_IT_Trigger: TIM Trigger Interrupt source. +* TIM_IT_Break: TIM Break Interrupt source. +* Return : bitstatus: SET or RESET. +*******************************************************************************/ +ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT) +{ + ITStatus bitstatus = RESET; + uint16_t itstatus = 0x0, itenable = 0x0; + + itstatus = TIMx->INTFR & TIM_IT; + + itenable = TIMx->DMAINTENR & TIM_IT; + if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET)) + { + bitstatus = SET; + } + else + { + bitstatus = RESET; + } + + return bitstatus; +} + +/******************************************************************************* +* Function Name : TIM_ClearITPendingBit +* Description : Clears the TIMx's interrupt pending bits. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* TIM_IT: specifies the pending bit to clear. +* TIM_IT_Update: TIM update Interrupt source. +* TIM_IT_CC1: TIM Capture Compare 1 Interrupt source. +* TIM_IT_CC2: TIM Capture Compare 2 Interrupt source. +* TIM_IT_CC3: TIM Capture Compare 3 Interrupt source. +* TIM_IT_CC4: TIM Capture Compare 4 Interrupt source. +* TIM_IT_COM: TIM Commutation Interrupt source. +* TIM_IT_Trigger: TIM Trigger Interrupt source. +* TIM_IT_Break: TIM Break Interrupt source. +* Return : None +*******************************************************************************/ +void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT) +{ + TIMx->INTFR = (uint16_t)~TIM_IT; +} + +/******************************************************************************* +* Function Name : TI1_Config +* Description : Configure the TI1 as Input. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* IM_ICPolarity : The Input Polarity. +* TIM_ICPolarity_Rising. +* TIM_ICPolarity_Falling. +* TIM_ICSelection: specifies the input to be used. +* TIM_ICSelection_DirectTI: TIM Input 1 is selected to be +* connected to IC1. +* TIM_ICSelection_IndirectTI: TIM Input 1 is selected to be +* connected to IC2. +* TIM_ICSelection_TRC: TIM Input 1 is selected to be connected +* to TRC. +* TIM_ICFilter: Specifies the Input Capture Filter. +* This parameter must be a value between 0x00 and 0x0F. +* Return : None +*******************************************************************************/ +static void TI1_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr1 = 0, tmpccer = 0; + + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CC1E); + tmpccmr1 = TIMx->CHCTLR1; + tmpccer = TIMx->CCER; + tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CC1S)) & ((uint16_t)~((uint16_t)TIM_IC1F))); + tmpccmr1 |= (uint16_t)(TIM_ICSelection | (uint16_t)(TIM_ICFilter << (uint16_t)4)); + + if((TIMx == TIM1) || (TIMx == TIM2) || (TIMx == TIM3)|| (TIMx == TIM4) || + (TIMx == TIM5) || (TIMx == TIM8) || (TIMx == TIM9)|| (TIMx == TIM10)) + { + tmpccer &= (uint16_t)~((uint16_t)(TIM_CC1P)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CC1E); + } + else + { + tmpccer &= (uint16_t)~((uint16_t)(TIM_CC1P | TIM_CC1NP)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CC1E); + } + + TIMx->CHCTLR1 = tmpccmr1; + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TI2_Config +* Description : Configure the TI2 as Input. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* IM_ICPolarity : The Input Polarity. +* TIM_ICPolarity_Rising. +* TIM_ICPolarity_Falling. +* TIM_ICSelection: specifies the input to be used. +* TIM_ICSelection_DirectTI: TIM Input 2 is selected to be +* connected to IC2. +* TIM_ICSelection_IndirectTI: TIM Input 2 is selected to be +* connected to IC1. +* TIM_ICSelection_TRC: TIM Input 2 is selected to be connected +* to TRC. +* TIM_ICFilter: Specifies the Input Capture Filter. +* This parameter must be a value between 0x00 and 0x0F. +* Return : None +*******************************************************************************/ +static void TI2_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr1 = 0, tmpccer = 0, tmp = 0; + + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CC2E); + tmpccmr1 = TIMx->CHCTLR1; + tmpccer = TIMx->CCER; + tmp = (uint16_t)(TIM_ICPolarity << 4); + tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CC2S)) & ((uint16_t)~((uint16_t)TIM_IC2F))); + tmpccmr1 |= (uint16_t)(TIM_ICFilter << 12); + tmpccmr1 |= (uint16_t)(TIM_ICSelection << 8); + + if((TIMx == TIM1) || (TIMx == TIM2) || (TIMx == TIM3)|| (TIMx == TIM4) || + (TIMx == TIM5) || (TIMx == TIM8) || (TIMx == TIM9)|| (TIMx == TIM10)) + { + tmpccer &= (uint16_t)~((uint16_t)(TIM_CC2P)); + tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CC2E); + } + else + { + tmpccer &= (uint16_t)~((uint16_t)(TIM_CC2P | TIM_CC2NP)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CC2E); + } + + TIMx->CHCTLR1 = tmpccmr1 ; + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TI3_Config +* Description : Configure the TI3 as Input. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* IM_ICPolarity : The Input Polarity. +* TIM_ICPolarity_Rising. +* TIM_ICPolarity_Falling. +* TIM_ICSelection: specifies the input to be used. +* TIM_ICSelection_DirectTI: TIM Input 3 is selected to be +* connected to IC3. +* TIM_ICSelection_IndirectTI: TIM Input 3 is selected to be +* connected to IC4. +* TIM_ICSelection_TRC: TIM Input 3 is selected to be connected +* to TRC. +* TIM_ICFilter: Specifies the Input Capture Filter. +* This parameter must be a value between 0x00 and 0x0F. +* Return : None +*******************************************************************************/ +static void TI3_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr2 = 0, tmpccer = 0, tmp = 0; + + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CC3E); + tmpccmr2 = TIMx->CHCTLR2; + tmpccer = TIMx->CCER; + tmp = (uint16_t)(TIM_ICPolarity << 8); + tmpccmr2 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CC3S)) & ((uint16_t)~((uint16_t)TIM_IC3F))); + tmpccmr2 |= (uint16_t)(TIM_ICSelection | (uint16_t)(TIM_ICFilter << (uint16_t)4)); + + if((TIMx == TIM1) || (TIMx == TIM2) || (TIMx == TIM3)|| (TIMx == TIM4) || + (TIMx == TIM5) || (TIMx == TIM8) || (TIMx == TIM9)|| (TIMx == TIM10)) + { + tmpccer &= (uint16_t)~((uint16_t)(TIM_CC3P)); + tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CC3E); + } + else + { + tmpccer &= (uint16_t)~((uint16_t)(TIM_CC3P | TIM_CC3NP)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CC3E); + } + + TIMx->CHCTLR2 = tmpccmr2; + TIMx->CCER = tmpccer; +} + +/******************************************************************************* +* Function Name : TI4_Config +* Description : Configure the TI4 as Input. +* Input : TIMx: where x can be 1 to 4 select the TIM peripheral. +* IM_ICPolarity : The Input Polarity. +* TIM_ICPolarity_Rising. +* TIM_ICPolarity_Falling. +* TIM_ICSelection: specifies the input to be used. +* TIM_ICSelection_DirectTI: TIM Input 4 is selected to be +* connected to IC4. +* TIM_ICSelection_IndirectTI: TIM Input 4 is selected to be +* connected to IC3. +* TIM_ICSelection_TRC: TIM Input 4 is selected to be connected +* to TRC. +* TIM_ICFilter: Specifies the Input Capture Filter. +* This parameter must be a value between 0x00 and 0x0F. +* Return : None +*******************************************************************************/ +static void TI4_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection, + uint16_t TIM_ICFilter) +{ + uint16_t tmpccmr2 = 0, tmpccer = 0, tmp = 0; + + TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CC4E); + tmpccmr2 = TIMx->CHCTLR2; + tmpccer = TIMx->CCER; + tmp = (uint16_t)(TIM_ICPolarity << 12); + tmpccmr2 &= (uint16_t)((uint16_t)(~(uint16_t)TIM_CC4S) & ((uint16_t)~((uint16_t)TIM_IC4F))); + tmpccmr2 |= (uint16_t)(TIM_ICSelection << 8); + tmpccmr2 |= (uint16_t)(TIM_ICFilter << 12); + + if((TIMx == TIM1) || (TIMx == TIM2) || (TIMx == TIM3)|| (TIMx == TIM4) || + (TIMx == TIM5) || (TIMx == TIM8) || (TIMx == TIM9)|| (TIMx == TIM10)) + { + tmpccer &= (uint16_t)~((uint16_t)(TIM_CC4P)); + tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CC4E); + } + else + { + tmpccer &= (uint16_t)~((uint16_t)(TIM_CC3P | TIM_CC4NP)); + tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CC4E); + } + + TIMx->CHCTLR2 = tmpccmr2; + TIMx->CCER = tmpccer; +} + + + + + + + + diff --git a/demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_usart.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_usart.c similarity index 50% rename from demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_usart.c rename to demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_usart.c index 5c3578ce..9cf06ebc 100644 --- a/demo/ch32/ch32v307/SRC/Peripheral/src/ch32v30x_usart.c +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_usart.c @@ -53,17 +53,13 @@ #define CTLR3_ONEBITE_Set ((uint16_t)0x0800) /* USART ONEBITE mode Enable Mask */ #define CTLR3_ONEBITE_Reset ((uint16_t)0xF7FF) /* USART ONEBITE mode Disable Mask */ - -/********************************************************************* - * @fn USART_DeInit - * - * @brief Deinitializes the USARTx peripheral registers to their default - * reset values. - * - * @param USARTx - where x can be 1, 2 or 3 to select the UART peripheral. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_DeInit +* Description : Deinitializes the USARTx peripheral registers to their default +* reset values. +* Input : USARTx: where x can be 1, 2 or 3 to select the UART peripheral. +* Return : None +*******************************************************************************/ void USART_DeInit(USART_TypeDef* USARTx) { if (USARTx == USART1) @@ -96,19 +92,15 @@ void USART_DeInit(USART_TypeDef* USARTx) } } -/********************************************************************* - * @fn USART_Init - * - * @brief Initializes the USARTx peripheral according to the specified - * parameters in the USART_InitStruct. - * - * @param USARTx - where x can be 1, 2 or 3 to select the UART peripheral. - * USART_InitStruct - pointer to a USART_InitTypeDef structure - * that contains the configuration information for the specified - * USART peripheral. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_Init +* Description : Initializes the USARTx peripheral according to the specified +* parameters in the USART_InitStruct. +* Input : USARTx: where x can be 1, 2 or 3 to select the UART peripheral. +* USART_InitStruct: pointer to a USART_InitTypeDef structure +* that contains the configuration information for the specified USART peripheral. +* Return : None +*******************************************************************************/ void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct) { uint32_t tmpreg = 0x00, apbclock = 0x00; @@ -173,15 +165,13 @@ void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct) USARTx->BRR = (uint16_t)tmpreg; } -/********************************************************************* - * @fn USART_StructInit - * - * @brief Fills each USART_InitStruct member with its default value. - * - * @param SPIx - where x can be 1, 2 or 3 to select the SPI peripheral. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_StructInit +* Description : Fills each USART_InitStruct member with its default value. +* Input : USART_InitStruct: pointer to a USART_InitTypeDef structure +* which will be initialized. +* Return : None +*******************************************************************************/ void USART_StructInit(USART_InitTypeDef* USART_InitStruct) { USART_InitStruct->USART_BaudRate = 9600; @@ -192,19 +182,16 @@ void USART_StructInit(USART_InitTypeDef* USART_InitStruct) USART_InitStruct->USART_HardwareFlowControl = USART_HardwareFlowControl_None; } -/********************************************************************* - * @fn USART_ClockInit - * - * @brief Initializes the USARTx peripheral Clock according to the - * specified parameters in the USART_ClockInitStruct . - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_ClockInitStruct - pointer to a USART_ClockInitTypeDef - * structure that contains the configuration information for the specified - * USART peripheral. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_ClockInit +* Description : Initializes the USARTx peripheral Clock according to the +* specified parameters in the USART_ClockInitStruct . +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_ClockInitStruct: pointer to a USART_ClockInitTypeDef +* structure that contains the configuration information for the specified +* USART peripheral. +* Return : None +*******************************************************************************/ void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct) { uint32_t tmpreg = 0x00; @@ -216,16 +203,13 @@ void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockI USARTx->CTLR2 = (uint16_t)tmpreg; } -/********************************************************************* - * @fn USART_ClockStructInit - * - * @brief Fills each USART_ClockStructInit member with its default value. - * - * @param USART_ClockInitStruct - pointer to a USART_ClockInitTypeDef - * structure which will be initialized. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_ClockStructInit +* Description : Fills each USART_ClockStructInit member with its default value. +* Input : USART_ClockInitStruct: pointer to a USART_ClockInitTypeDef +* structure which will be initialized. +* Return : None +*******************************************************************************/ void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct) { USART_ClockInitStruct->USART_Clock = USART_Clock_Disable; @@ -234,17 +218,13 @@ void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct) USART_ClockInitStruct->USART_LastBit = USART_LastBit_Disable; } -/********************************************************************* - * @fn USART_Cmd - * - * @brief Enables or disables the specified USART peripheral. - * reset values (Affects also the I2Ss). - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * NewState: ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_Cmd +* Description : Enables or disables the specified USART peripheral. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState) { if (NewState != DISABLE) @@ -257,26 +237,22 @@ void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState) } } -/********************************************************************* - * @fn USART_ITConfig - * - * @brief Enables or disables the specified USART interrupts. - * reset values (Affects also the I2Ss). - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_IT - specifies the USART interrupt sources to be enabled or disabled. - * USART_IT_CTS - CTS change interrupt. - * USART_IT_LBD - LIN Break detection interrupt. - * USART_IT_TXE - Transmit Data Register empty interrupt. - * USART_IT_TC - Transmission complete interrupt. - * USART_IT_RXNE - Receive Data register not empty interrupt. - * USART_IT_IDLE - Idle line detection interrupt. - * USART_IT_PE - Parity Error interrupt. - * USART_IT_ERR - Error interrupt. - * NewState - ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_ITConfig +* Description : Enables or disables the specified USART interrupts. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_IT: specifies the USART interrupt sources to be enabled or disabled. +* USART_IT_CTS: CTS change interrupt. +* USART_IT_LBD: LIN Break detection interrupt. +* USART_IT_TXE: Transmit Data Register empty interrupt. +* USART_IT_TC: Transmission complete interrupt. +* USART_IT_RXNE: Receive Data register not empty interrupt. +* USART_IT_IDLE: Idle line detection interrupt. +* USART_IT_PE: Parity Error interrupt. +* USART_IT_ERR: Error interrupt. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState) { uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00; @@ -314,19 +290,16 @@ void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState Ne } } -/********************************************************************* - * @fn USART_DMACmd - * - * @brief Enables or disables the USART DMA interface. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_DMAReq - specifies the DMA request. - * USART_DMAReq_Tx - USART DMA transmit request. - * USART_DMAReq_Rx - USART DMA receive request. - * NewState - ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_DMACmd +* Description : Enables or disables the USART DMA interface. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_DMAReq: specifies the DMA request. +* USART_DMAReq_Tx: USART DMA transmit request. +* USART_DMAReq_Rx: USART DMA receive request. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState) { if (NewState != DISABLE) @@ -339,50 +312,41 @@ void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState } } -/********************************************************************* - * @fn USART_SetAddress - * - * @brief Sets the address of the USART node. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_Address - Indicates the address of the USART node. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_SetAddress +* Description : Sets the address of the USART node. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_Address: Indicates the address of the USART node. +* Return : None +*******************************************************************************/ void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address) { USARTx->CTLR2 &= CTLR2_Address_Mask; USARTx->CTLR2 |= USART_Address; } -/********************************************************************* - * @fn USART_WakeUpConfig - * - * @brief Selects the USART WakeUp method. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_WakeUp - specifies the USART wakeup method. - * USART_WakeUp_IdleLine - WakeUp by an idle line detection. - * USART_WakeUp_AddressMark - WakeUp by an address mark. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_WakeUpConfig +* Description : Selects the USART WakeUp method. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_WakeUp: specifies the USART wakeup method. +* USART_WakeUp_IdleLine: WakeUp by an idle line detection. +* USART_WakeUp_AddressMark: WakeUp by an address mark. +* Return : None +*******************************************************************************/ void USART_WakeUpConfig(USART_TypeDef* USARTx, uint16_t USART_WakeUp) { USARTx->CTLR1 &= CTLR1_WAKE_Mask; USARTx->CTLR1 |= USART_WakeUp; } -/********************************************************************* - * @fn USART_ReceiverWakeUpCmd - * - * @brief Determines if the USART is in mute mode or not. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * NewState - ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_ReceiverWakeUpCmd +* Description : Determines if the USART is in mute mode or not. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState) { if (NewState != DISABLE) @@ -395,34 +359,28 @@ void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState) } } -/********************************************************************* - * @fn USART_LINBreakDetectLengthConfig - * - * @brief Sets the USART LIN Break detection length. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_LINBreakDetectLength - specifies the LIN break detection length. - * USART_LINBreakDetectLength_10b - 10-bit break detection. - * USART_LINBreakDetectLength_11b - 11-bit break detection. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_LINBreakDetectLengthConfig +* Description : Sets the USART LIN Break detection length. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_LINBreakDetectLength: specifies the LIN break detection length. +* USART_LINBreakDetectLength_10b: 10-bit break detection. +* USART_LINBreakDetectLength_11b: 11-bit break detection. +* Return : None +*******************************************************************************/ void USART_LINBreakDetectLengthConfig(USART_TypeDef* USARTx, uint16_t USART_LINBreakDetectLength) { USARTx->CTLR2 &= CTLR2_LBDL_Mask; USARTx->CTLR2 |= USART_LINBreakDetectLength; } -/********************************************************************* - * @fn USART_LINCmd - * - * @brief Enables or disables the USART LIN mode. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * NewState - ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_LINCmd +* Description : Enables or disables the USART LIN mode. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState) { if (NewState != DISABLE) @@ -435,91 +393,73 @@ void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState) } } -/********************************************************************* - * @fn USART_SendData - * - * @brief Transmits single data through the USARTx peripheral. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * Data - the data to transmit. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_SendData +* Description : Transmits single data through the USARTx peripheral. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* Data: the data to transmit.. +* Return : None +*******************************************************************************/ void USART_SendData(USART_TypeDef* USARTx, uint16_t Data) { USARTx->DATAR = (Data & (uint16_t)0x01FF); } -/********************************************************************* - * @fn USART_ReceiveData - * - * @brief Returns the most recent received data by the USARTx peripheral. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * - * @return The received data. - */ +/******************************************************************************* +* Function Name : USART_ReceiveData +* Description : Returns the most recent received data by the USARTx peripheral. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* Return : The received data. +*******************************************************************************/ uint16_t USART_ReceiveData(USART_TypeDef* USARTx) { return (uint16_t)(USARTx->DATAR & (uint16_t)0x01FF); } -/********************************************************************* - * @fn USART_SendBreak - * - * @brief Transmits break characters. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_SendBreak +* Description : Transmits break characters. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* Return : None +*******************************************************************************/ void USART_SendBreak(USART_TypeDef* USARTx) { USARTx->CTLR1 |= CTLR1_SBK_Set; } -/********************************************************************* - * @fn USART_SetGuardTime - * - * @brief Sets the specified USART guard time. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_GuardTime - specifies the guard time. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_SetGuardTime +* Description : Sets the specified USART guard time. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_GuardTime: specifies the guard time. +* Return : None +*******************************************************************************/ void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime) { USARTx->GPR &= GPR_LSB_Mask; USARTx->GPR |= (uint16_t)((uint16_t)USART_GuardTime << 0x08); } -/********************************************************************* - * @fn USART_SetPrescaler - * - * @brief Sets the system clock prescaler. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_Prescaler - specifies the prescaler clock. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_SetPrescaler +* Description : Sets the system clock prescaler. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_Prescaler: specifies the prescaler clock. +* Return : None +*******************************************************************************/ void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler) { USARTx->GPR &= GPR_MSB_Mask; USARTx->GPR |= USART_Prescaler; } -/********************************************************************* - * @fn USART_SmartCardCmd - * - * @brief Enables or disables the USART Smart Card mode. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * NewState - ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_SmartCardCmd +* Description : Enables or disables the USART Smart Card mode. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState) { if (NewState != DISABLE) @@ -532,16 +472,13 @@ void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState) } } -/********************************************************************* - * @fn USART_SmartCardNACKCmd - * - * @brief Enables or disables NACK transmission. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * NewState - ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_SmartCardNACKCmd +* Description : Enables or disables NACK transmission. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState) { if (NewState != DISABLE) @@ -554,16 +491,13 @@ void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState) } } -/********************************************************************* - * @fn USART_HalfDuplexCmd - * - * @brief Enables or disables the USART Half Duplex communication. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * NewState - ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_HalfDuplexCmd +* Description : Enables or disables the USART Half Duplex communication. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState) { if (NewState != DISABLE) @@ -576,16 +510,13 @@ void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState) } } -/********************************************************************* - * @fn USART_OverSampling8Cmd - * - * @brief Enables or disables the USART's 8x oversampling mode. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * NewState - ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_OverSampling8Cmd +* Description : Enables or disables the USART's 8x oversampling mode. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState) { if (NewState != DISABLE) @@ -598,16 +529,13 @@ void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState) } } -/********************************************************************* - * @fn USART_OneBitMethodCmd - * - * @brief Enables or disables the USART's one bit sampling method. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * NewState - ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_OneBitMethodCmd +* Description : Enables or disables the USART's one bit sampling method. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState) { if (NewState != DISABLE) @@ -620,34 +548,28 @@ void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState) } } -/********************************************************************* - * @fn USART_IrDAConfig - * - * @brief Configures the USART's IrDA interface. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_IrDAMode - specifies the IrDA mode. - * USART_IrDAMode_LowPower. - * USART_IrDAMode_Normal. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_IrDAConfig +* Description : Configures the USART's IrDA interface. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_IrDAMode: specifies the IrDA mode. +* USART_IrDAMode_LowPower. +* USART_IrDAMode_Normal. +* Return : None +*******************************************************************************/ void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode) { USARTx->CTLR3 &= CTLR3_IRLP_Mask; USARTx->CTLR3 |= USART_IrDAMode; } -/********************************************************************* - * @fn USART_IrDACmd - * - * @brief Enables or disables the USART's IrDA interface. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * NewState - ENABLE or DISABLE. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_IrDACmd +* Description : Enables or disables the USART's IrDA interface. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* NewState: ENABLE or DISABLE. +* Return : None +*******************************************************************************/ void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState) { if (NewState != DISABLE) @@ -660,26 +582,23 @@ void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState) } } -/********************************************************************* - * @fn USART_GetFlagStatus - * - * @brief Checks whether the specified USART flag is set or not. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_FLAG - specifies the flag to check. - * USART_FLAG_CTS - CTS Change flag. - * USART_FLAG_LBD - LIN Break detection flag. - * USART_FLAG_TXE - Transmit data register empty flag. - * USART_FLAG_TC - Transmission Complete flag. - * USART_FLAG_RXNE - Receive data register not empty flag. - * USART_FLAG_IDLE - Idle Line detection flag. - * USART_FLAG_ORE - OverRun Error flag. - * USART_FLAG_NE - Noise Error flag. - * USART_FLAG_FE - Framing Error flag. - * USART_FLAG_PE - Parity Error flag. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_GetFlagStatus +* Description : Checks whether the specified USART flag is set or not. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_FLAG: specifies the flag to check. +* USART_FLAG_CTS: CTS Change flag. +* USART_FLAG_LBD: LIN Break detection flag. +* USART_FLAG_TXE: Transmit data register empty flag. +* USART_FLAG_TC: Transmission Complete flag. +* USART_FLAG_RXNE: Receive data register not empty flag. +* USART_FLAG_IDLE: Idle Line detection flag. +* USART_FLAG_ORE: OverRun Error flag. +* USART_FLAG_NE: Noise Error flag. +* USART_FLAG_FE: Framing Error flag. +* USART_FLAG_PE: Parity Error flag. +* Return : bitstatus: SET or RESET. +*******************************************************************************/ FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG) { FlagStatus bitstatus = RESET; @@ -699,20 +618,17 @@ FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG) return bitstatus; } -/********************************************************************* - * @fn USART_ClearFlag - * - * @brief Clears the USARTx's pending flags. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_FLAG - specifies the flag to clear. - * USART_FLAG_CTS - CTS Change flag. - * USART_FLAG_LBD - LIN Break detection flag. - * USART_FLAG_TC - Transmission Complete flag. - * USART_FLAG_RXNE - Receive data register not empty flag. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_ClearFlag +* Description : Clears the USARTx's pending flags. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_FLAG: specifies the flag to clear. +* USART_FLAG_CTS: CTS Change flag. +* USART_FLAG_LBD: LIN Break detection flag. +* USART_FLAG_TC: Transmission Complete flag. +* USART_FLAG_RXNE: Receive data register not empty flag. +* Return : None +*******************************************************************************/ void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG) { if ((USART_FLAG & USART_FLAG_CTS) == USART_FLAG_CTS) @@ -722,27 +638,24 @@ void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG) USARTx->STATR = (uint16_t)~USART_FLAG; } -/********************************************************************* - * @fn USART_GetITStatus - * - * @brief Checks whether the specified USART interrupt has occurred or not. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_IT - specifies the USART interrupt source to check. - * USART_IT_CTS - CTS change interrupt. - * USART_IT_LBD - LIN Break detection interrupt. - * USART_IT_TXE - Tansmit Data Register empty interrupt. - * USART_IT_TC - Transmission complete interrupt. - * USART_IT_RXNE - Receive Data register not empty interrupt. - * USART_IT_IDLE - Idle line detection interrupt. - * USART_IT_ORE_RX - OverRun Error interrupt if the RXNEIE bit is set. - * USART_IT_ORE_ER - OverRun Error interrupt if the EIE bit is set. - * USART_IT_NE - Noise Error interrupt. - * USART_IT_FE - Framing Error interrupt. - * USART_IT_PE - Parity Error interrupt. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_GetITStatus +* Description : Checks whether the specified USART interrupt has occurred or not. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_IT: specifies the USART interrupt source to check. +* USART_IT_CTS: CTS change interrupt. +* USART_IT_LBD: LIN Break detection interrupt. +* USART_IT_TXE: Tansmit Data Register empty interrupt. +* USART_IT_TC: Transmission complete interrupt. +* USART_IT_RXNE: Receive Data register not empty interrupt. +* USART_IT_IDLE: Idle line detection interrupt. +* USART_IT_ORE_RX : OverRun Error interrupt if the RXNEIE bit is set. +* USART_IT_ORE_ER : OverRun Error interrupt if the EIE bit is set. +* USART_IT_NE: Noise Error interrupt. +* USART_IT_FE: Framing Error interrupt. +* USART_IT_PE: Parity Error interrupt. +* Return : bitstatus: SET or RESET. +*******************************************************************************/ ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT) { uint32_t bitpos = 0x00, itmask = 0x00, usartreg = 0x00; @@ -785,20 +698,17 @@ ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT) return bitstatus; } -/********************************************************************* - * @fn USART_ClearITPendingBit - * - * @brief Clears the USARTx's interrupt pending bits. - * - * @param USARTx - where x can be 1, 2, 3 to select the USART peripheral. - * USART_IT - specifies the interrupt pending bit to clear. - * USART_IT_CTS - CTS change interrupt. - * USART_IT_LBD - LIN Break detection interrupt. - * USART_IT_TC - Transmission complete interrupt. - * USART_IT_RXNE - Receive Data register not empty interrupt. - * - * @return none - */ +/******************************************************************************* +* Function Name : USART_ClearITPendingBit +* Description : Clears the USARTx's interrupt pending bits. +* Input : USARTx: where x can be 1, 2, 3 to select the USART peripheral. +* USART_IT: specifies the interrupt pending bit to clear. +* USART_IT_CTS: CTS change interrupt. +* USART_IT_LBD: LIN Break detection interrupt. +* USART_IT_TC: Transmission complete interrupt. +* USART_IT_RXNE: Receive Data register not empty interrupt. +* Return : None +*******************************************************************************/ void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT) { uint16_t bitpos = 0x00, itmask = 0x00; diff --git a/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_wwdg.c b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_wwdg.c new file mode 100644 index 00000000..822d7d34 --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/Peripheral/src/ch32v30x_wwdg.c @@ -0,0 +1,123 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : ch32v30x_wwdg.c +* Author : WCH +* Version : V1.0.0 +* Date : 2021/06/06 +* Description : This file provides all the WWDG firmware functions. +**********************************************************************************/ +#include "ch32v30x_wwdg.h" +#include "ch32v30x_rcc.h" + +/* CTLR register bit mask */ +#define CTLR_WDGA_Set ((uint32_t)0x00000080) + +/* CFGR register bit mask */ +#define CFGR_WDGTB_Mask ((uint32_t)0xFFFFFE7F) +#define CFGR_W_Mask ((uint32_t)0xFFFFFF80) +#define BIT_Mask ((uint8_t)0x7F) + +/******************************************************************************** +* Function Name : WWDG_DeInit +* Description : Deinitializes the WWDG peripheral registers to their default reset values +* Input : None +* Return : None +*********************************************************************************/ +void WWDG_DeInit(void) +{ + RCC_APB1PeriphResetCmd(RCC_APB1Periph_WWDG, ENABLE); + RCC_APB1PeriphResetCmd(RCC_APB1Periph_WWDG, DISABLE); +} + +/******************************************************************************** +* Function Name : WWDG_SetPrescaler +* Description : Sets the WWDG Prescaler +* Input : WWDG_Prescaler: specifies the WWDG Prescaler +* WWDG_Prescaler_1: WWDG counter clock = (PCLK1/4096)/1 +* WWDG_Prescaler_2: WWDG counter clock = (PCLK1/4096)/2 +* WWDG_Prescaler_4: WWDG counter clock = (PCLK1/4096)/4 +* WWDG_Prescaler_8: WWDG counter clock = (PCLK1/4096)/8 +* Return : None +*********************************************************************************/ +void WWDG_SetPrescaler(uint32_t WWDG_Prescaler) +{ + uint32_t tmpreg = 0; + tmpreg = WWDG->CFGR & CFGR_WDGTB_Mask; + tmpreg |= WWDG_Prescaler; + WWDG->CFGR = tmpreg; +} + +/******************************************************************************** +* Function Name : WWDG_SetWindowValue +* Description : Sets the WWDG window value +* Input : WindowValue: specifies the window value to be compared to the +* downcounter,which must be lower than 0x80 +* Return : None +*********************************************************************************/ +void WWDG_SetWindowValue(uint8_t WindowValue) +{ + __IO uint32_t tmpreg = 0; + + tmpreg = WWDG->CFGR & CFGR_W_Mask; + + tmpreg |= WindowValue & (uint32_t) BIT_Mask; + + WWDG->CFGR = tmpreg; +} + +/******************************************************************************** +* Function Name : WWDG_EnableIT +* Description : Enables the WWDG Early Wakeup interrupt(EWI) +* Input : None +* Return : None +*********************************************************************************/ +void WWDG_EnableIT(void) +{ + WWDG->CFGR |= (1<<9); +} + +/******************************************************************************** +* Function Name : WWDG_SetCounter +* Description : Sets the WWDG counter value +* Input : Counter: specifies the watchdog counter value,which must be a +* number between 0x40 and 0x7F +* Return : None +*********************************************************************************/ +void WWDG_SetCounter(uint8_t Counter) +{ + WWDG->CTLR = Counter & BIT_Mask; +} + + +/******************************************************************************** +* Function Name : WWDG_Enable +* Description : Enables WWDG and load the counter value +* Input : Counter: specifies the watchdog counter value,which must be a +* number between 0x40 and 0x7F +* Return : None +*********************************************************************************/ +void WWDG_Enable(uint8_t Counter) +{ + WWDG->CTLR = CTLR_WDGA_Set | Counter; +} + +/******************************************************************************** +* Function Name : WWDG_GetFlagStatus +* Description : Checks whether the Early Wakeup interrupt flag is set or not +* Input : None +* Return : The new state of the Early Wakeup interrupt flag (SET or RESET) +*********************************************************************************/ +FlagStatus WWDG_GetFlagStatus(void) +{ + return (FlagStatus)(WWDG->STATR); +} + +/******************************************************************************** +* Function Name : WWDG_ClearFlag +* Description : Clears Early Wakeup interrupt flag +* Input : None +* Return : None +*********************************************************************************/ +void WWDG_ClearFlag(void) +{ + WWDG->STATR = (uint32_t)RESET; +} diff --git a/demo/ch32/ch32v307/SRC/Startup/startup_ch32v30x.S b/demo/ch32/usb_device/CH32V307VCT6/Startup/startup_ch32v30x.S similarity index 100% rename from demo/ch32/ch32v307/SRC/Startup/startup_ch32v30x.S rename to demo/ch32/usb_device/CH32V307VCT6/Startup/startup_ch32v30x.S diff --git a/demo/stm32/usb_device/stm32f103c8t6/example/cdc/cdc_init.c b/demo/ch32/usb_device/CH32V307VCT6/User/cdc_acm_template.c similarity index 62% rename from demo/stm32/usb_device/stm32f103c8t6/example/cdc/cdc_init.c rename to demo/ch32/usb_device/CH32V307VCT6/User/cdc_acm_template.c index a5005151..48c53fd7 100644 --- a/demo/stm32/usb_device/stm32f103c8t6/example/cdc/cdc_init.c +++ b/demo/ch32/usb_device/CH32V307VCT6/User/cdc_acm_template.c @@ -1,32 +1,10 @@ -/** @mainpage cdc_demo_init - * - *
Project cdc_demo - *
Author LiGuo 1570139720@qq.com - *
- * @section cdc class init demo - * - * -# You can use USB to create a virtual serial port - * - * @section 版本更新历史 - * - * 版本|作者|时间|描述 - * ----|----|----|---- - * 1.0|LiGuo|2021.11.19|creat project - * - *

© Copyright 2021 LiGuo. - * All rights reserved.

- ********************************************************************************* - */ - -/* include ------------------------------------------------------------------*/ -#include "main.h" #include "usbd_core.h" #include "usbd_cdc.h" /*!< endpoint address */ #define CDC_IN_EP 0x81 -#define CDC_OUT_EP 0x01 -#define CDC_INT_EP 0x82 +#define CDC_OUT_EP 0x02 +#define CDC_INT_EP 0x83 #define USBD_VID 0xFFFF #define USBD_PID 0xFFFF @@ -38,7 +16,7 @@ /*!< global descriptor */ static const uint8_t cdc_descriptor[] = { - USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x02, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02), /////////////////////////////////////// @@ -48,33 +26,35 @@ static const uint8_t cdc_descriptor[] = { /////////////////////////////////////// /// string1 descriptor /////////////////////////////////////// - 0x12, /* bLength */ + 0x14, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ /////////////////////////////////////// /// string2 descriptor /////////////////////////////////////// - 0x24, /* bLength */ + 0x26, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ - ' ', 0x00, /* wcChar8 */ - 'C', 0x00, /* wcChar9 */ - 'D', 0x00, /* wcChar10 */ - 'C', 0x00, /* wcChar11 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ + ' ', 0x00, /* wcChar9 */ + 'C', 0x00, /* wcChar10 */ + 'D', 0x00, /* wcChar11 */ + 'C', 0x00, /* wcChar12 */ ' ', 0x00, /* wcChar13 */ 'D', 0x00, /* wcChar14 */ 'E', 0x00, /* wcChar15 */ @@ -88,13 +68,13 @@ static const uint8_t cdc_descriptor[] = { '2', 0x00, /* wcChar0 */ '0', 0x00, /* wcChar1 */ '2', 0x00, /* wcChar2 */ - '1', 0x00, /* wcChar3 */ - '0', 0x00, /* wcChar4 */ - '3', 0x00, /* wcChar5 */ - '1', 0x00, /* wcChar6 */ - '0', 0x00, /* wcChar7 */ - '0', 0x00, /* wcChar8 */ - '0', 0x00, /* wcChar9 */ + '2', 0x00, /* wcChar3 */ + '1', 0x00, /* wcChar4 */ + '2', 0x00, /* wcChar5 */ + '3', 0x00, /* wcChar6 */ + '4', 0x00, /* wcChar7 */ + '5', 0x00, /* wcChar8 */ + '6', 0x00, /* wcChar9 */ #ifdef CONFIG_USB_HS /////////////////////////////////////// /// device qualifier descriptor @@ -112,6 +92,7 @@ static const uint8_t cdc_descriptor[] = { #endif 0x00 }; + /*!< class */ usbd_class_t cdc_class; /*!< interface one */ @@ -124,7 +105,7 @@ void usbd_cdc_acm_out(uint8_t ep) { uint8_t data[64]; uint32_t read_byte; - + usbd_ep_read(ep, data, 64, &read_byte); printf("read len:%d\r\n", read_byte); usbd_ep_read(ep, NULL, 0, NULL); @@ -147,7 +128,7 @@ usbd_endpoint_t cdc_in_ep = { }; /* function ------------------------------------------------------------------*/ -void cdc_init(void) +void cdc_acm_init(void) { usbd_desc_register(cdc_descriptor); /*!< add interface */ @@ -156,6 +137,9 @@ void cdc_init(void) /*!< interface add endpoint */ usbd_interface_add_endpoint(&cdc_data_intf, &cdc_out_ep); usbd_interface_add_endpoint(&cdc_data_intf, &cdc_in_ep); + + extern int usb_dc_init(void); + usb_dc_init(); } volatile uint8_t dtr_enable = 0; @@ -169,11 +153,10 @@ void usbd_cdc_acm_set_dtr(bool dtr) } } -void cdc_test(void) +void cdc_acm_data_send_with_dtr_test(void) { if (dtr_enable) { uint8_t data_buffer[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x31, 0x32, 0x33, 0x34, 0x35 }; usbd_ep_write(CDC_IN_EP, data_buffer, 10, NULL); - HAL_Delay(500); } -} +} \ No newline at end of file diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/ch32v30x_conf.h b/demo/ch32/usb_device/CH32V307VCT6/User/ch32v30x_conf.h similarity index 54% rename from demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/ch32v30x_conf.h rename to demo/ch32/usb_device/CH32V307VCT6/User/ch32v30x_conf.h index da55fd7f..0d0e39bf 100644 --- a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/ch32v30x_conf.h +++ b/demo/ch32/usb_device/CH32V307VCT6/User/ch32v30x_conf.h @@ -8,9 +8,27 @@ #ifndef __CH32V30x_CONF_H #define __CH32V30x_CONF_H +#include "ch32v30x_adc.h" +#include "ch32v30x_bkp.h" +#include "ch32v30x_can.h" +#include "ch32v30x_crc.h" +#include "ch32v30x_dac.h" +#include "ch32v30x_dbgmcu.h" +#include "ch32v30x_dma.h" +#include "ch32v30x_exti.h" +#include "ch32v30x_flash.h" +#include "ch32v30x_fsmc.h" #include "ch32v30x_gpio.h" +#include "ch32v30x_i2c.h" +#include "ch32v30x_iwdg.h" +#include "ch32v30x_pwr.h" #include "ch32v30x_rcc.h" +#include "ch32v30x_rtc.h" +#include "ch32v30x_sdio.h" +#include "ch32v30x_spi.h" +#include "ch32v30x_tim.h" #include "ch32v30x_usart.h" +#include "ch32v30x_wwdg.h" #include "ch32v30x_it.h" #include "ch32v30x_misc.h" diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/ch32v30x_it.c b/demo/ch32/usb_device/CH32V307VCT6/User/ch32v30x_it.c similarity index 60% rename from demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/ch32v30x_it.c rename to demo/ch32/usb_device/CH32V307VCT6/User/ch32v30x_it.c index 8820881b..9a89c49a 100644 --- a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/ch32v30x_it.c +++ b/demo/ch32/usb_device/CH32V307VCT6/User/ch32v30x_it.c @@ -10,24 +10,22 @@ void NMI_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); void HardFault_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); -/********************************************************************* - * @fn NMI_Handler - * - * @brief This function handles NMI exception. - * - * @return none - */ +/******************************************************************************* +* Function Name : NMI_Handler +* Description : This function handles NMI exception. +* Input : None +* Return : None +*******************************************************************************/ void NMI_Handler(void) { } -/********************************************************************* - * @fn HardFault_Handler - * - * @brief This function handles Hard Fault exception. - * - * @return none - */ +/******************************************************************************* +* Function Name : HardFault_Handler +* Description : This function handles Hard Fault exception. +* Input : None +* Return : None +*******************************************************************************/ void HardFault_Handler(void) { while (1) diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/ch32v30x_it.h b/demo/ch32/usb_device/CH32V307VCT6/User/ch32v30x_it.h similarity index 100% rename from demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/ch32v30x_it.h rename to demo/ch32/usb_device/CH32V307VCT6/User/ch32v30x_it.h diff --git a/demo/ch32/usb_device/CH32V307VCT6/User/main.c b/demo/ch32/usb_device/CH32V307VCT6/User/main.c new file mode 100644 index 00000000..5628cdbd --- /dev/null +++ b/demo/ch32/usb_device/CH32V307VCT6/User/main.c @@ -0,0 +1,63 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : main.c +* Author : sakumisu +* Version : V1.0.0 +* Date : 2022/01/02 +* Description : cdc acm test. +*******************************************************************************/ + +/* + *@Note +*/ +#include "debug.h" +#include "usbd_core.h" +#include "usbd_cdc.h" + +void usb_dc_low_level_init(void) +{ + RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY); + RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE); + RCC_USBHSConfig(RCC_USBPLL_Div2); + RCC_USBHSPLLCKREFCLKConfig(RCC_USBHSPLLCKREFCLK_4M); + RCC_USBHSPHYPLLALIVEcmd(ENABLE); +#ifdef CONFIG_USB_HS + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE); +#else + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_OTG_FS, ENABLE); +#endif + + Delay_Us(100); +#ifndef CONFIG_USB_HS + //EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN; + NVIC_EnableIRQ(OTG_FS_IRQn); +#else + NVIC_EnableIRQ( USBHS_IRQn ); +#endif +} + +/********************************************************************* + * @fn main + * + * @brief Main program. + * + * @return none + */ +int main(void) +{ + Delay_Init(); + USART_Printf_Init(115200); + printf("SystemClk:%d\r\n", SystemCoreClock); + + Delay_Ms(10); + + extern void cdc_acm_init(void); + cdc_acm_init(); + + while (!usb_device_is_configured()) { + } + while (1) { + extern void cdc_acm_data_send_with_dtr_test(); + cdc_acm_data_send_with_dtr_test(); + Delay_Ms(500); + } +} diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/system_ch32v30x.c b/demo/ch32/usb_device/CH32V307VCT6/User/system_ch32v30x.c similarity index 76% rename from demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/system_ch32v30x.c rename to demo/ch32/usb_device/CH32V307VCT6/User/system_ch32v30x.c index d43096be..d9b4cf57 100644 --- a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/system_ch32v30x.c +++ b/demo/ch32/usb_device/CH32V307VCT6/User/system_ch32v30x.c @@ -72,14 +72,13 @@ static void SetSysClock(void); #endif -/********************************************************************* - * @fn SystemInit - * - * @brief Setup the microcontroller system Initialize the Embedded Flash Interface, - * the PLL and update the SystemCoreClock variable. - * - * @return none - */ +/****************************************************************************************** +* Function Name : SystemInit +* Description : Setup the microcontroller system Initialize the Embedded Flash Interface, +* the PLL and update the SystemCoreClock variable. +* Input : None +* Return : None +*******************************************************************************************/ void SystemInit (void) { RCC->CTLR |= (uint32_t)0x00000001; @@ -91,17 +90,17 @@ void SystemInit (void) SetSysClock(); } -/********************************************************************* - * @fn SystemCoreClockUpdate - * - * @brief Update SystemCoreClock variable according to Clock Register Values. - * - * @return none - */ + +/****************************************************************************************** +* Function Name : SystemCoreClockUpdate +* Description : Update SystemCoreClock variable according to Clock Register Values. +* Input : None +* Return : None +*******************************************************************************************/ void SystemCoreClockUpdate (void) { uint32_t tmp = 0, pllmull = 0, pllsource = 0, Pll_6_5 = 0; - + tmp = RCC->CFGR0 & RCC_SWS; switch (tmp) @@ -116,7 +115,7 @@ void SystemCoreClockUpdate (void) pllmull = RCC->CFGR0 & RCC_PLLMULL; pllsource = RCC->CFGR0 & RCC_PLLSRC; pllmull = ( pllmull >> 18) + 2; - + if(((*(uint32_t*)0x1FFFF70C) & (1<<14)) != (1<<14)){ /* for other CH32V30x */ if(pllmull == 17) pllmull = 18; } @@ -129,7 +128,7 @@ void SystemCoreClockUpdate (void) if(pllmull == 16) pllmull = 15; if(pllmull == 17) pllmull = 16; } - + if (pllsource == 0x00) { SystemCoreClock = (HSI_VALUE >> 1) * pllmull; @@ -158,13 +157,13 @@ void SystemCoreClockUpdate (void) SystemCoreClock >>= tmp; } -/********************************************************************* - * @fn SetSysClock - * - * @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers. - * - * @return none - */ + +/****************************************************************************************** +* Function Name : SetSysClock +* Description : Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers. +* Input : None +* Return : None +*******************************************************************************************/ static void SetSysClock(void) { #ifdef SYSCLK_FREQ_HSE @@ -177,6 +176,7 @@ static void SetSysClock(void) SetSysClockTo56(); #elif defined SYSCLK_FREQ_72MHz SetSysClockTo72(); + #elif defined SYSCLK_FREQ_96MHz SetSysClockTo96(); #elif defined SYSCLK_FREQ_120MHz @@ -184,26 +184,27 @@ static void SetSysClock(void) #elif defined SYSCLK_FREQ_144MHz SetSysClockTo144(); + #endif /* If none of the define above is enabled, the HSI is used as System clock * source (default after reset) - */ + */ } #ifdef SYSCLK_FREQ_HSE -/********************************************************************* - * @fn SetSysClockToHSE - * - * @brief Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers. - * - * @return none - */ +/****************************************************************************************** +* Function Name : SetSysClockToHSE +* Description : Sets HSE as System clock source and configure HCLK, PCLK2 and PCLK1 prescalers. +* Input : None +* Return : None +*******************************************************************************************/ static void SetSysClockToHSE(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; + RCC->CTLR |= ((uint32_t)RCC_HSEON); @@ -225,7 +226,12 @@ static void SetSysClockToHSE(void) if (HSEStatus == (uint32_t)0x01) { - /* HCLK = SYSCLK */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + /* Flash 0 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_0; + + /* HCLK = SYSCLK */ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; /* PCLK2 = HCLK */ RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1; @@ -243,21 +249,20 @@ static void SetSysClockToHSE(void) } else { - /* If HSE fails to start-up, the application will have wrong clock + /* If HSE fails to start-up, the application will have wrong clock * configuration. User can add here some code to deal with this error - */ + */ } } #elif defined SYSCLK_FREQ_24MHz -/********************************************************************* - * @fn SetSysClockTo24 - * - * @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2 and PCLK1 prescalers. - * - * @return none - */ +/****************************************************************************************** +* Function Name : SetSysClockTo24 +* Description : Sets System clock frequency to 24MHz and configure HCLK, PCLK2 and PCLK1 prescalers. +* Input : None +* Return : None +*******************************************************************************************/ static void SetSysClockTo24(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; @@ -281,6 +286,13 @@ static void SetSysClockTo24(void) } if (HSEStatus == (uint32_t)0x01) { + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 0 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_0; + /* HCLK = SYSCLK */ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; /* PCLK2 = HCLK */ @@ -298,7 +310,7 @@ static void SetSysClockTo24(void) } /* Enable PLL */ RCC->CTLR |= RCC_PLLON; - + /* Wait till PLL is ready */ while((RCC->CTLR & RCC_PLLRDY) == 0) { @@ -313,21 +325,20 @@ static void SetSysClockTo24(void) } else { - /* If HSE fails to start-up, the application will have wrong clock + /* If HSE fails to start-up, the application will have wrong clock * configuration. User can add here some code to deal with this error - */ + */ } } #elif defined SYSCLK_FREQ_48MHz -/********************************************************************* - * @fn SetSysClockTo48 - * - * @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers. - * - * @return none - */ +/****************************************************************************************** +* Function Name : SetSysClockTo48 +* Description : Sets System clock frequency to 48MHz and configure HCLK, PCLK2 and PCLK1 prescalers. +* Input : None +* Return : None +*******************************************************************************************/ static void SetSysClockTo48(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; @@ -352,6 +363,13 @@ static void SetSysClockTo48(void) if (HSEStatus == (uint32_t)0x01) { + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 1 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_1; + /* HCLK = SYSCLK */ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; /* PCLK2 = HCLK */ @@ -385,22 +403,21 @@ static void SetSysClockTo48(void) } else { - /* - * If HSE fails to start-up, the application will have wrong clock + /* + * If HSE fails to start-up, the application will have wrong clock * configuration. User can add here some code to deal with this error - */ + */ } } #elif defined SYSCLK_FREQ_56MHz -/********************************************************************* - * @fn SetSysClockTo56 - * - * @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers. - * - * @return none - */ +/****************************************************************************************** +* Function Name : SetSysClockTo56 +* Description : Sets System clock frequency to 56MHz and configure HCLK, PCLK2 and PCLK1 prescalers. +* Input : None +* Return : None +*******************************************************************************************/ static void SetSysClockTo56(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; @@ -425,6 +442,13 @@ static void SetSysClockTo56(void) if (HSEStatus == (uint32_t)0x01) { + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 2 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2; + /* HCLK = SYSCLK */ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; /* PCLK2 = HCLK */ @@ -459,22 +483,21 @@ static void SetSysClockTo56(void) } else { - /* - * If HSE fails to start-up, the application will have wrong clock + /* + * If HSE fails to start-up, the application will have wrong clock * configuration. User can add here some code to deal with this error - */ + */ } } #elif defined SYSCLK_FREQ_72MHz -/********************************************************************* - * @fn SetSysClockTo72 - * - * @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers. - * - * @return none - */ +/****************************************************************************************** +* Function Name : SetSysClockTo72 +* Description : Sets System clock frequency to 72MHz and configure HCLK, PCLK2 and PCLK1 prescalers. +* Input : None +* Return : None +*******************************************************************************************/ static void SetSysClockTo72(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; @@ -499,6 +522,13 @@ static void SetSysClockTo72(void) if (HSEStatus == (uint32_t)0x01) { + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 2 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2; + /* HCLK = SYSCLK */ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; /* PCLK2 = HCLK */ @@ -506,7 +536,7 @@ static void SetSysClockTo72(void) /* PCLK1 = HCLK */ RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2; - /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ + /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */ RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE | RCC_PLLMULL)); @@ -533,23 +563,22 @@ static void SetSysClockTo72(void) } else { - /* - * If HSE fails to start-up, the application will have wrong clock + /* + * If HSE fails to start-up, the application will have wrong clock * configuration. User can add here some code to deal with this error - */ + */ } } #elif defined SYSCLK_FREQ_96MHz -/********************************************************************* - * @fn SetSysClockTo96 - * - * @brief Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers. - * - * @return none - */ +/****************************************************************************************** +* Function Name : SetSysClockTo96 +* Description : Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers. +* Input : None +* Return : None +*******************************************************************************************/ static void SetSysClockTo96(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; @@ -574,6 +603,13 @@ static void SetSysClockTo96(void) if (HSEStatus == (uint32_t)0x01) { + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 2 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2; + /* HCLK = SYSCLK */ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; /* PCLK2 = HCLK */ @@ -618,13 +654,12 @@ static void SetSysClockTo96(void) #elif defined SYSCLK_FREQ_120MHz -/********************************************************************* - * @fn SetSysClockTo120 - * - * @brief Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers. - * - * @return none - */ +/****************************************************************************************** +* Function Name : SetSysClockTo120 +* Description : Sets System clock frequency to 120MHz and configure HCLK, PCLK2 and PCLK1 prescalers. +* Input : None +* Return : None +*******************************************************************************************/ static void SetSysClockTo120(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; @@ -649,6 +684,13 @@ static void SetSysClockTo120(void) if (HSEStatus == (uint32_t)0x01) { + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 2 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2; + /* HCLK = SYSCLK */ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; /* PCLK2 = HCLK */ @@ -693,13 +735,12 @@ static void SetSysClockTo120(void) #elif defined SYSCLK_FREQ_144MHz -/********************************************************************* - * @fn SetSysClockTo144 - * - * @brief Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers. - * - * @return none - */ +/****************************************************************************************** +* Function Name : SetSysClockTo144 +* Description : Sets System clock frequency to 144MHz and configure HCLK, PCLK2 and PCLK1 prescalers. +* Input : None +* Return : None +*******************************************************************************************/ static void SetSysClockTo144(void) { __IO uint32_t StartUpCounter = 0, HSEStatus = 0; @@ -724,6 +765,13 @@ static void SetSysClockTo144(void) if (HSEStatus == (uint32_t)0x01) { + /* Enable Prefetch Buffer */ + FLASH->ACTLR |= FLASH_ACTLR_PRFTBE; + + /* Flash 2 wait state */ + FLASH->ACTLR &= (uint32_t)((uint32_t)~FLASH_ACTLR_LATENCY); + FLASH->ACTLR |= (uint32_t)FLASH_ACTLR_LATENCY_2; + /* HCLK = SYSCLK */ RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1; /* PCLK2 = HCLK */ @@ -766,4 +814,6 @@ static void SetSysClockTo144(void) } + + #endif diff --git a/demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/system_ch32v30x.h b/demo/ch32/usb_device/CH32V307VCT6/User/system_ch32v30x.h similarity index 100% rename from demo/ch32/ch32v307/USB/USBFS/DEVICE/cdc_acm/User/system_ch32v30x.h rename to demo/ch32/usb_device/CH32V307VCT6/User/system_ch32v30x.h diff --git a/demo/stm32/usb_device/stm32f103c8t6/example/hid_custom/hid_custom_init.c b/demo/hid_custom_keyboard_template.c similarity index 84% rename from demo/stm32/usb_device/stm32f103c8t6/example/hid_custom/hid_custom_init.c rename to demo/hid_custom_keyboard_template.c index d8913a98..b4041018 100644 --- a/demo/stm32/usb_device/stm32f103c8t6/example/hid_custom/hid_custom_init.c +++ b/demo/hid_custom_keyboard_template.c @@ -1,29 +1,3 @@ -/** @mainpage hid_custom_demo_init - * - *
Project hid_custom_demo - *
Author LiGuo 1570139720@qq.com - *
- * @section hid custom init demo - * - * -# You can use this demo to create a hid composite device - * such as keyboard + mouse + hidraw - * use two interface and four endpoint - * the first interface :keyboard ! ep1_in:0x81 ! ep1_out:0x01 - * the second interface :hidraw ! ep2_in:0x82 ! ep2_out:0x02 - * - * @section 版本更新历史 - * - * 版本|作者|时间|描述 - * ----|----|----|---- - * 1.0|LiGuo|2021.11.19|creat project - * - *

© Copyright 2021 LiGuo. - * All rights reserved.

- ********************************************************************************* - */ - -/* include ------------------------------------------------------------------*/ -#include "main.h" #include "usbd_core.h" #include "usbd_hid.h" @@ -160,40 +134,40 @@ static const uint8_t hid_descriptor[] = { /////////////////////////////////////// /// string1 descriptor /////////////////////////////////////// - 0x12, /* bLength */ + 0x14, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ /////////////////////////////////////// /// string2 descriptor /////////////////////////////////////// - 0x28, /* bLength */ + 0x26, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ - ' ', 0x00, /* wcChar8 */ - 'H', 0x00, /* wcChar9 */ - 'I', 0x00, /* wcChar10 */ - 'D', 0x00, /* wcChar11 */ - ' ', 0x00, /* wcChar12 */ - 'C', 0x00, /* wcChar13 */ - 'U', 0x00, /* wcChar14 */ - 'S', 0x00, /* wcChar15 */ - 'T', 0x00, /* wcChar16 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ + ' ', 0x00, /* wcChar9 */ + 'H', 0x00, /* wcChar10 */ + 'I', 0x00, /* wcChar11 */ + 'D', 0x00, /* wcChar12 */ + ' ', 0x00, /* wcChar13 */ + 'D', 0x00, /* wcChar14 */ + 'E', 0x00, /* wcChar15 */ + 'M', 0x00, /* wcChar16 */ 'O', 0x00, /* wcChar17 */ - 'M', 0x00, /* wcChar18 */ /////////////////////////////////////// /// string3 descriptor /////////////////////////////////////// @@ -202,13 +176,13 @@ static const uint8_t hid_descriptor[] = { '2', 0x00, /* wcChar0 */ '0', 0x00, /* wcChar1 */ '2', 0x00, /* wcChar2 */ - '1', 0x00, /* wcChar3 */ - '0', 0x00, /* wcChar4 */ - '3', 0x00, /* wcChar5 */ - '1', 0x00, /* wcChar6 */ - '0', 0x00, /* wcChar7 */ - '0', 0x00, /* wcChar8 */ - '0', 0x00, /* wcChar9 */ + '2', 0x00, /* wcChar3 */ + '1', 0x00, /* wcChar4 */ + '2', 0x00, /* wcChar5 */ + '3', 0x00, /* wcChar6 */ + '4', 0x00, /* wcChar7 */ + '5', 0x00, /* wcChar8 */ + '6', 0x00, /* wcChar9 */ #ifdef CONFIG_USB_HS /////////////////////////////////////// /// device qualifier descriptor @@ -320,10 +294,7 @@ static void usbd_hid_kbd_out_callback(uint8_t ep) } if (led_state & HID_KBD_LED_CAPS_LOCK) { /*!< caps lock */ - /*!< do what you like */ - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0); } else { - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 1); } if (led_state & HID_KBD_LED_SCROLL_LOCK) { @@ -390,7 +361,7 @@ static usbd_endpoint_t custom_out_ep = { * @param[in] none * @retval none */ -void hid_custom_init(void) +void hid_custom_keyboard_init(void) { usbd_desc_register(hid_descriptor); /*!< add interface ! the first interface */ @@ -410,14 +381,8 @@ void hid_custom_init(void) /*!< register report descriptor interface 1 */ usbd_hid_report_descriptor_register(1, hid_custom_report_desc, HID_CUSTOM_REPORT_DESC_SIZE); - /*!< user init a gpio pc13 test capslk led */ - /*!< enable gpioc clock */ - __HAL_RCC_GPIOC_CLK_ENABLE(); - /*!< set pc13 is out put */ - GPIOC->CRH &= 0XFF0FFFFF; - GPIOC->CRH |= 0X00000003 << (13 - 8) * 4; - - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0); + extern int usb_dc_init(void); + usb_dc_init(); } /** @@ -472,14 +437,14 @@ void hid_custom_test(void) uint8_t sendbuffer1[8] = { 0x00, 0x00, HID_KEY_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A hid_keyboard_send_report(KBD_IN_EP, sendbuffer1, KBD_IN_EP_SIZE); /*!< delay 10ms */ - HAL_Delay(10); + //HAL_Delay(10); /*!< send button up */ sendbuffer1[2] = 0; hid_keyboard_send_report(KBD_IN_EP, sendbuffer1, KBD_IN_EP_SIZE); /*!< delay 1000ms the custom test */ - HAL_Delay(1000); + //HAL_Delay(1000); /*!< custom test */ uint8_t sendbuffer2[64] = { 6 }; hid_custom_send_report(HIDRAW_IN_EP, sendbuffer2, HIDRAW_IN_SIZE); - HAL_Delay(1000); + //HAL_Delay(1000); } \ No newline at end of file diff --git a/demo/stm32/usb_device/stm32f103c8t6/example/hid_keyboard/hid_keyboard_init.c b/demo/hid_keyboard_template.c similarity index 57% rename from demo/stm32/usb_device/stm32f103c8t6/example/hid_keyboard/hid_keyboard_init.c rename to demo/hid_keyboard_template.c index c05ee76b..15531379 100644 --- a/demo/stm32/usb_device/stm32f103c8t6/example/hid_keyboard/hid_keyboard_init.c +++ b/demo/hid_keyboard_template.c @@ -1,50 +1,18 @@ -/** @mainpage hid_keyboard_demo_init - * - *
Project hid_keyboard_demo - *
Author LiGuo 1570139720@qq.com - *
- * @section hid keyboard init demo - * - * -# You can use USB to create a hid keyboard - * - * @section 版本更新历史 - * - * 版本|作者|时间|描述 - * ----|----|----|---- - * 1.0|LiGuo|2021.11.19|creat project - * - *

© Copyright 2021 LiGuo. - * All rights reserved.

- ********************************************************************************* - */ - -/* include ------------------------------------------------------------------*/ -#include "main.h" #include "usbd_core.h" #include "usbd_hid.h" -#define HID_STATE_IDLE 0 -#define HID_STATE_BUSY 1 - -/*!< endpoint address */ -#define HID_INT_EP 0x81 -#define HID_INT_EP_SIZE 8 -#define HID_INT_EP_INTERVAL 10 - #define USBD_VID 0xffff #define USBD_PID 0xffff #define USBD_MAX_POWER 100 #define USBD_LANGID_STRING 1033 -/*!< hid state ! Data can be sent only when state is idle */ -uint8_t hid_state = HID_STATE_IDLE; +#define HID_INT_EP 0x81 +#define HID_INT_EP_SIZE 8 +#define HID_INT_EP_INTERVAL 10 -/*!< config descriptor size */ -#define USB_HID_CONFIG_DESC_SIZ 34 -/*!< report descriptor size */ +#define USB_HID_CONFIG_DESC_SIZ 34 #define HID_KEYBOARD_REPORT_DESC_SIZE 63 -/*!< global descriptor */ static const uint8_t hid_descriptor[] = { USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0002, 0x01), USB_CONFIG_DESCRIPTOR_INIT(USB_HID_CONFIG_DESC_SIZ, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), @@ -88,42 +56,40 @@ static const uint8_t hid_descriptor[] = { /////////////////////////////////////// /// string1 descriptor /////////////////////////////////////// - 0x12, /* bLength */ + 0x14, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ /////////////////////////////////////// /// string2 descriptor /////////////////////////////////////// - 0x2C, /* bLength */ + 0x26, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ - ' ', 0x00, /* wcChar8 */ - 'H', 0x00, /* wcChar9 */ - 'I', 0x00, /* wcChar10 */ - 'D', 0x00, /* wcChar11 */ - ' ', 0x00, /* wcChar12 */ - 'K', 0x00, /* wcChar13 */ - 'E', 0x00, /* wcChar14 */ - 'Y', 0x00, /* wcChar15 */ - 'B', 0x00, /* wcChar16 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ + ' ', 0x00, /* wcChar9 */ + 'H', 0x00, /* wcChar10 */ + 'I', 0x00, /* wcChar11 */ + 'D', 0x00, /* wcChar12 */ + ' ', 0x00, /* wcChar13 */ + 'D', 0x00, /* wcChar14 */ + 'E', 0x00, /* wcChar15 */ + 'M', 0x00, /* wcChar16 */ 'O', 0x00, /* wcChar17 */ - 'A', 0x00, /* wcChar18 */ - 'R', 0x00, /* wcChar19 */ - 'D', 0x00, /* wcChar20 */ /////////////////////////////////////// /// string3 descriptor /////////////////////////////////////// @@ -132,13 +98,13 @@ static const uint8_t hid_descriptor[] = { '2', 0x00, /* wcChar0 */ '0', 0x00, /* wcChar1 */ '2', 0x00, /* wcChar2 */ - '1', 0x00, /* wcChar3 */ - '0', 0x00, /* wcChar4 */ - '3', 0x00, /* wcChar5 */ - '1', 0x00, /* wcChar6 */ - '0', 0x00, /* wcChar7 */ - '0', 0x00, /* wcChar8 */ - '0', 0x00, /* wcChar9 */ + '2', 0x00, /* wcChar3 */ + '1', 0x00, /* wcChar4 */ + '2', 0x00, /* wcChar5 */ + '3', 0x00, /* wcChar6 */ + '4', 0x00, /* wcChar7 */ + '5', 0x00, /* wcChar8 */ + '6', 0x00, /* wcChar9 */ #ifdef CONFIG_USB_HS /////////////////////////////////////// /// device qualifier descriptor @@ -157,7 +123,20 @@ static const uint8_t hid_descriptor[] = { 0x00 }; -/*!< hid keyboard report descriptor */ +/* USB HID device Configuration Descriptor */ +static uint8_t hid_desc[9] __ALIGN_END = { + /* 18 */ + 0x09, /* bLength: HID Descriptor size */ + HID_DESCRIPTOR_TYPE_HID, /* bDescriptorType: HID */ + 0x11, /* bcdHID: HID Class Spec release number */ + 0x01, + 0x00, /* bCountryCode: Hardware target country */ + 0x01, /* bNumDescriptors: Number of HID class descriptors to follow */ + 0x22, /* bDescriptorType */ + HID_KEYBOARD_REPORT_DESC_SIZE, /* wItemLength: Total length of Report descriptor */ + 0x00, +}; + static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) @@ -193,76 +172,26 @@ static const uint8_t hid_keyboard_report_desc[HID_KEYBOARD_REPORT_DESC_SIZE] = { 0xc0 // END_COLLECTION }; -/*!< class */ static usbd_class_t hid_class; - -/*!< interface */ static usbd_interface_t hid_intf; -/* function ------------------------------------------------------------------*/ -static void usbd_hid_int_callback(uint8_t ep) +void usbd_hid_int_callback(uint8_t ep) { - /*!< endpoint call back */ - /*!< transfer successfully */ - if (hid_state == HID_STATE_BUSY) { - /*!< update the state */ - hid_state = HID_STATE_IDLE; - } + uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KEY_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A + usbd_ep_write(HID_INT_EP, sendbuffer, 8, NULL); } - -/*!< endpoint call back */ static usbd_endpoint_t hid_in_ep = { .ep_cb = usbd_hid_int_callback, .ep_addr = 0x81 }; -/* function ------------------------------------------------------------------*/ -/** - * @brief hid keyborad init - * @pre none - * @param[in] none - * @retval none - */ void hid_keyboard_init(void) { usbd_desc_register(hid_descriptor); - /*!< add interface */ usbd_hid_add_interface(&hid_class, &hid_intf); - /*!< interface add endpoint */ usbd_interface_add_endpoint(&hid_intf, &hid_in_ep); - /*!< register report descriptor */ usbd_hid_report_descriptor_register(0, hid_keyboard_report_desc, HID_KEYBOARD_REPORT_DESC_SIZE); -} -/** - * @brief device send report to host - * @pre none - * @param[in] ep endpoint address - * @param[in] data Points to the data buffer waiting to be sent - * @param[in] len Length of data to be sent - * @retval none - */ -void hid_keyboard_send_report(uint8_t ep, uint8_t *data, uint8_t len) -{ - if (usb_device_is_configured()) { - if (hid_state == HID_STATE_IDLE) { - /*!< updata the state */ - hid_state = HID_STATE_BUSY; - /*!< write buffer */ - usbd_ep_write(ep, data, len, NULL); - } - } -} - -/** - * @brief hid keyborad test - * @pre none - * @param[in] none - * @retval none - */ -void hid_keyboard_test(void) -{ - uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KEY_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A - hid_keyboard_send_report(HID_INT_EP, sendbuffer, HID_INT_EP_SIZE); - HAL_Delay(1000); -} + extern int usb_dc_init(void); + usb_dc_init(); +} \ No newline at end of file diff --git a/demo/stm32/usb_device/stm32f103c8t6/example/hid_mouse/hid_mouse_init.c b/demo/hid_mouse_template.c similarity index 77% rename from demo/stm32/usb_device/stm32f103c8t6/example/hid_mouse/hid_mouse_init.c rename to demo/hid_mouse_template.c index be2ac453..c2e00f2f 100644 --- a/demo/stm32/usb_device/stm32f103c8t6/example/hid_mouse/hid_mouse_init.c +++ b/demo/hid_mouse_template.c @@ -1,25 +1,3 @@ -/** @mainpage hid_mouse_demo_init - * - *
Project hid_mouse_demo - *
Author LiGuo 1570139720@qq.com - *
- * @section hid mouse init demo - * - * -# You can use USB to create a hid mouse - * - * @section 版本更新历史 - * - * 版本|作者|时间|描述 - * ----|----|----|---- - * 1.0|LiGuo|2021.11.19|creat project - * - *

© Copyright 2021 LiGuo. - * All rights reserved.

- ********************************************************************************* - */ - -/* include ------------------------------------------------------------------*/ -#include "main.h" #include "usbd_core.h" #include "usbd_hid.h" @@ -88,39 +66,40 @@ const uint8_t hid_descriptor[] = { /////////////////////////////////////// /// string1 descriptor /////////////////////////////////////// - 0x12, /* bLength */ + 0x14, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ /////////////////////////////////////// /// string2 descriptor /////////////////////////////////////// 0x26, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ - ' ', 0x00, /* wcChar8 */ - 'H', 0x00, /* wcChar9 */ - 'I', 0x00, /* wcChar10 */ - 'D', 0x00, /* wcChar11 */ - ' ', 0x00, /* wcChar12 */ - 'M', 0x00, /* wcChar13 */ - 'O', 0x00, /* wcChar14 */ - 'U', 0x00, /* wcChar15 */ - 'S', 0x00, /* wcChar16 */ - 'E', 0x00, /* wcChar17 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ + ' ', 0x00, /* wcChar9 */ + 'H', 0x00, /* wcChar10 */ + 'I', 0x00, /* wcChar11 */ + 'D', 0x00, /* wcChar12 */ + ' ', 0x00, /* wcChar13 */ + 'D', 0x00, /* wcChar14 */ + 'E', 0x00, /* wcChar15 */ + 'M', 0x00, /* wcChar16 */ + 'O', 0x00, /* wcChar17 */ /////////////////////////////////////// /// string3 descriptor /////////////////////////////////////// @@ -129,13 +108,13 @@ const uint8_t hid_descriptor[] = { '2', 0x00, /* wcChar0 */ '0', 0x00, /* wcChar1 */ '2', 0x00, /* wcChar2 */ - '1', 0x00, /* wcChar3 */ - '0', 0x00, /* wcChar4 */ - '3', 0x00, /* wcChar5 */ - '1', 0x00, /* wcChar6 */ - '0', 0x00, /* wcChar7 */ - '0', 0x00, /* wcChar8 */ - '0', 0x00, /* wcChar9 */ + '2', 0x00, /* wcChar3 */ + '1', 0x00, /* wcChar4 */ + '2', 0x00, /* wcChar5 */ + '3', 0x00, /* wcChar6 */ + '4', 0x00, /* wcChar7 */ + '5', 0x00, /* wcChar8 */ + '6', 0x00, /* wcChar9 */ #ifdef CONFIG_USB_HS /////////////////////////////////////// /// device qualifier descriptor @@ -254,6 +233,9 @@ void hid_mouse_init(void) usbd_interface_add_endpoint(&hid_intf, &hid_in_ep); /*!< register report descriptor */ usbd_hid_report_descriptor_register(0, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE); + + extern int usb_dc_init(void); + usb_dc_init(); /*!< init mouse report data */ mouse_cfg.buttons = 0; mouse_cfg.wheel = 0; @@ -287,7 +269,7 @@ void hid_mouse_send_report(uint8_t ep, uint8_t *data, uint8_t len) * @param[in] none * @retval none */ -void hid_mouse_test(void) +void hid_mouse_send_report_test(void) { /*!< remove mouse pointer */ mouse_cfg.x += 10; @@ -295,5 +277,4 @@ void hid_mouse_test(void) /*!< send repotr to host */ hid_mouse_send_report(HID_INT_EP, (uint8_t *)&mouse_cfg, 4); /*!< delay 1000ms */ - HAL_Delay(1000); } \ No newline at end of file diff --git a/demo/mm32/KEIL_PRJ/USB_VCOM.uvoptx b/demo/mm32/KEIL_PRJ/USB_VCOM.uvoptx index f8a6e45b..066c440b 100644 --- a/demo/mm32/KEIL_PRJ/USB_VCOM.uvoptx +++ b/demo/mm32/KEIL_PRJ/USB_VCOM.uvoptx @@ -249,6 +249,18 @@ 0 0 + + 3 + 5 + 1 + 0 + 0 + 0 + ..\..\cdc_acm_template.c + cdc_acm_template.c + 0 + 0 + @@ -259,7 +271,7 @@ 0 4 - 5 + 6 1 0 0 @@ -271,7 +283,7 @@ 4 - 6 + 7 1 0 0 @@ -285,13 +297,13 @@ usb_stack - 0 + 1 0 0 0 5 - 7 + 8 1 0 0 @@ -303,7 +315,7 @@ 5 - 8 + 9 1 0 0 @@ -315,13 +327,13 @@ 5 - 9 + 10 1 0 0 0 - ..\..\..\port\mm32\usb_dc.c - usb_dc.c + ..\..\..\port\mm32\usb_dc_mm32.c + usb_dc_mm32.c 0 0 diff --git a/demo/mm32/KEIL_PRJ/USB_VCOM.uvprojx b/demo/mm32/KEIL_PRJ/USB_VCOM.uvprojx index 97985b95..ae300539 100644 --- a/demo/mm32/KEIL_PRJ/USB_VCOM.uvprojx +++ b/demo/mm32/KEIL_PRJ/USB_VCOM.uvprojx @@ -413,6 +413,11 @@ 1 ..\bsp\main.c + + cdc_acm_template.c + 1 + ..\..\cdc_acm_template.c + @@ -444,9 +449,9 @@ ..\..\..\core\usbd_core.c - usb_dc.c + usb_dc_mm32.c 1 - ..\..\..\port\mm32\usb_dc.c + ..\..\..\port\mm32\usb_dc_mm32.c diff --git a/demo/mm32/bsp/main.c b/demo/mm32/bsp/main.c index 5094214b..2b6dbe45 100644 --- a/demo/mm32/bsp/main.c +++ b/demo/mm32/bsp/main.c @@ -35,141 +35,6 @@ void DelayMs(u32 ulMs) } } -/*!< endpoint address */ -#define CDC_IN_EP 0x81 -#define CDC_OUT_EP 0x02 -#define CDC_INT_EP 0x83 - -#define USBD_VID 0xFFFF -#define USBD_PID 0xFFFF -#define USBD_MAX_POWER 100 -#define USBD_LANGID_STRING 1033 - -/*!< config descriptor size */ -#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN) - -/*!< global descriptor */ -static const uint8_t cdc_descriptor[] = { - USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x02, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), - USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), - CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02), - /////////////////////////////////////// - /// string0 descriptor - /////////////////////////////////////// - USB_LANGID_INIT(USBD_LANGID_STRING), - /////////////////////////////////////// - /// string1 descriptor - /////////////////////////////////////// - 0x12, /* bLength */ - USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ - /////////////////////////////////////// - /// string2 descriptor - /////////////////////////////////////// - 0x24, /* bLength */ - USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ - ' ', 0x00, /* wcChar8 */ - 'C', 0x00, /* wcChar9 */ - 'D', 0x00, /* wcChar10 */ - 'C', 0x00, /* wcChar11 */ - ' ', 0x00, /* wcChar13 */ - 'D', 0x00, /* wcChar14 */ - 'E', 0x00, /* wcChar15 */ - 'M', 0x00, /* wcChar16 */ - 'O', 0x00, /* wcChar17 */ - /////////////////////////////////////// - /// string3 descriptor - /////////////////////////////////////// - 0x16, /* bLength */ - USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - '2', 0x00, /* wcChar0 */ - '0', 0x00, /* wcChar1 */ - '2', 0x00, /* wcChar2 */ - '1', 0x00, /* wcChar3 */ - '0', 0x00, /* wcChar4 */ - '3', 0x00, /* wcChar5 */ - '1', 0x00, /* wcChar6 */ - '0', 0x00, /* wcChar7 */ - '0', 0x00, /* wcChar8 */ - '0', 0x00, /* wcChar9 */ -#ifdef CONFIG_USB_HS - /////////////////////////////////////// - /// device qualifier descriptor - /////////////////////////////////////// - 0x0a, - USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, - 0x00, - 0x02, - 0x02, - 0x02, - 0x01, - 0x40, - 0x01, - 0x00, -#endif - 0x00 -}; -/*!< class */ -usbd_class_t cdc_class; -/*!< interface one */ -usbd_interface_t cdc_cmd_intf; -/*!< interface two */ -usbd_interface_t cdc_data_intf; - -/* function ------------------------------------------------------------------*/ -void usbd_cdc_acm_out(uint8_t ep) -{ - uint8_t data[64]; - uint32_t read_byte; - - usbd_ep_read(ep, data, 64, &read_byte); - printf("read len:%d\r\n", read_byte); - usbd_ep_read(ep, NULL, 0, NULL); -} - -void usbd_cdc_acm_in(uint8_t ep) -{ - printf("in\r\n"); -} - -/*!< endpoint call back */ -usbd_endpoint_t cdc_out_ep = { - .ep_addr = CDC_OUT_EP, - .ep_cb = usbd_cdc_acm_out -}; - -usbd_endpoint_t cdc_in_ep = { - .ep_addr = CDC_IN_EP, - .ep_cb = usbd_cdc_acm_in -}; - -/* function ------------------------------------------------------------------*/ -void cdc_init(void) -{ - usbd_desc_register(cdc_descriptor); - /*!< add interface */ - usbd_cdc_add_acm_interface(&cdc_class, &cdc_cmd_intf); - usbd_cdc_add_acm_interface(&cdc_class, &cdc_data_intf); - /*!< interface add endpoint */ - usbd_interface_add_endpoint(&cdc_data_intf, &cdc_out_ep); - usbd_interface_add_endpoint(&cdc_data_intf, &cdc_in_ep); -} - void usb_dc_low_level_init(void) { RCC->APB1ENR |= RCC_APB1ENR_USBEN; //ʹUSBʱ @@ -178,16 +43,7 @@ void usb_dc_low_level_init(void) MY_NVIC_Init(1, 1, USB_HP_CAN1_TX_IRQn, 2); //USBж } -volatile uint8_t dtr_enable = 0; -void usbd_cdc_acm_set_dtr(bool dtr) -{ - if (dtr) { - dtr_enable = 1; - } else { - dtr_enable = 0; - } -} /******************************************************************************************************** **Ϣ main(void) ** @@ -204,18 +60,14 @@ int main(void) printf("UART OK!\r\n"); - cdc_init(); - extern int usb_dc_init(void); - usb_dc_init(); + extern void cdc_acm_init(void); + cdc_acm_init(); + while(1) { - if(dtr_enable) - { - uint8_t data_buffer[10] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x31, 0x32, 0x33, 0x34, 0x35 }; - usbd_ep_write(CDC_IN_EP, data_buffer, 10, NULL); + extern void cdc_acm_data_send_with_dtr_test(void); + cdc_acm_data_send_with_dtr_test(); DelayMs(1000); - } - } } diff --git a/demo/stm32/usb_device/stm32f103c8t6/example/msc_ram/msc_ram_init.c b/demo/msc_ram_template.c similarity index 56% rename from demo/stm32/usb_device/stm32f103c8t6/example/msc_ram/msc_ram_init.c rename to demo/msc_ram_template.c index 71bafb05..70965924 100644 --- a/demo/stm32/usb_device/stm32f103c8t6/example/msc_ram/msc_ram_init.c +++ b/demo/msc_ram_template.c @@ -1,24 +1,3 @@ -/** @mainpage msc_ram_demo_init - * - *
Project msc_ram_demo - *
Author LiGuo 1570139720@qq.com - *
- * @section msc ram init demo - * - * - * @section 汾ʷ - * - * 汾||ʱ| - * ----|----|----|---- - * 1.0|LiGuo|2021.11.19|creat project - * - *

© Copyright 2021 LiGuo. - * All rights reserved.

- ********************************************************************************* - */ - -/* include ------------------------------------------------------------------*/ -#include "main.h" #include "usbd_core.h" #include "usbd_msc.h" @@ -43,38 +22,40 @@ const uint8_t msc_ram_descriptor[] = { /////////////////////////////////////// /// string1 descriptor /////////////////////////////////////// - 0x12, /* bLength */ + 0x14, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ /////////////////////////////////////// /// string2 descriptor /////////////////////////////////////// - 0x24, /* bLength */ + 0x26, /* bLength */ USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */ - 'B', 0x00, /* wcChar0 */ - 'o', 0x00, /* wcChar1 */ - 'u', 0x00, /* wcChar2 */ - 'f', 0x00, /* wcChar3 */ - 'f', 0x00, /* wcChar4 */ - 'a', 0x00, /* wcChar5 */ - 'l', 0x00, /* wcChar6 */ - 'o', 0x00, /* wcChar7 */ - ' ', 0x00, /* wcChar8 */ - 'M', 0x00, /* wcChar9 */ - 'S', 0x00, /* wcChar10 */ - 'C', 0x00, /* wcChar11 */ - ' ', 0x00, /* wcChar12 */ - 'D', 0x00, /* wcChar13 */ - 'E', 0x00, /* wcChar14 */ - 'M', 0x00, /* wcChar15 */ - 'O', 0x00, /* wcChar16 */ + 'C', 0x00, /* wcChar0 */ + 'h', 0x00, /* wcChar1 */ + 'e', 0x00, /* wcChar2 */ + 'r', 0x00, /* wcChar3 */ + 'r', 0x00, /* wcChar4 */ + 'y', 0x00, /* wcChar5 */ + 'U', 0x00, /* wcChar6 */ + 'S', 0x00, /* wcChar7 */ + 'B', 0x00, /* wcChar8 */ + ' ', 0x00, /* wcChar9 */ + 'M', 0x00, /* wcChar10 */ + 'S', 0x00, /* wcChar11 */ + 'C', 0x00, /* wcChar12 */ + ' ', 0x00, /* wcChar13 */ + 'D', 0x00, /* wcChar14 */ + 'E', 0x00, /* wcChar15 */ + 'M', 0x00, /* wcChar16 */ + 'O', 0x00, /* wcChar17 */ /////////////////////////////////////// /// string3 descriptor /////////////////////////////////////// @@ -83,13 +64,13 @@ const uint8_t msc_ram_descriptor[] = { '2', 0x00, /* wcChar0 */ '0', 0x00, /* wcChar1 */ '2', 0x00, /* wcChar2 */ - '1', 0x00, /* wcChar3 */ - '0', 0x00, /* wcChar4 */ - '3', 0x00, /* wcChar5 */ - '1', 0x00, /* wcChar6 */ - '0', 0x00, /* wcChar7 */ - '0', 0x00, /* wcChar8 */ - '0', 0x00, /* wcChar9 */ + '2', 0x00, /* wcChar3 */ + '1', 0x00, /* wcChar4 */ + '2', 0x00, /* wcChar5 */ + '3', 0x00, /* wcChar6 */ + '4', 0x00, /* wcChar7 */ + '5', 0x00, /* wcChar8 */ + '6', 0x00, /* wcChar9 */ #ifdef CONFIG_USB_HS /////////////////////////////////////// /// device qualifier descriptor @@ -148,4 +129,7 @@ void msc_ram_init(void) { usbd_desc_register(msc_ram_descriptor); usbd_msc_class_init(MSC_OUT_EP, MSC_IN_EP); + + extern int usb_dc_init(void); + usb_dc_init(); } diff --git a/demo/stm32/usb_device/stm32f103c8t6/Core/Src/main.c b/demo/stm32/usb_device/stm32f103c8t6/Core/Src/main.c index 6dfe4239..ccbb6cd7 100644 --- a/demo/stm32/usb_device/stm32f103c8t6/Core/Src/main.c +++ b/demo/stm32/usb_device/stm32f103c8t6/Core/Src/main.c @@ -23,7 +23,6 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "usbd_core.h" -#include "example_select.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -86,81 +85,50 @@ extern void usb_dc_init(void); */ int main(void) { - /* USER CODE BEGIN 1 */ + /* USER CODE BEGIN 1 */ - /* USER CODE END 1 */ + /* USER CODE END 1 */ - /* MCU Configuration--------------------------------------------------------*/ + /* MCU Configuration--------------------------------------------------------*/ - /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ - HAL_Init(); + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); - /* USER CODE BEGIN Init */ + /* USER CODE BEGIN Init */ - /* USER CODE END Init */ + /* USER CODE END Init */ - /* Configure the system clock */ - SystemClock_Config(); + /* Configure the system clock */ + SystemClock_Config(); - /* USER CODE BEGIN SysInit */ + /* USER CODE BEGIN SysInit */ - /* USER CODE END SysInit */ + /* USER CODE END SysInit */ - /* Initialize all configured peripherals */ - MX_GPIO_Init(); - MX_USART1_UART_Init(); - //MX_USB_PCD_Init(); - /* USER CODE BEGIN 2 */ + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_USART1_UART_Init(); + //MX_USB_PCD_Init(); + /* USER CODE BEGIN 2 */ -#ifdef USB_CDC - /*!< demo init */ - extern void cdc_init(void); - cdc_init(); -#elif defined USB_HID_KEYBOARD - extern void hid_keyboard_init(void); - hid_keyboard_init(); -#elif defined USB_HID_MOUSE - extern void hid_mouse_init(void); - hid_mouse_init(); -#elif defined USB_HID_CUSTOM - extern void hid_custom_init(void); - hid_custom_init(); -#elif defined USB_MSC_RAM - extern void msc_ram_init(void); - msc_ram_init(); -#endif + extern void cdc_acm_init(void); + cdc_acm_init(); - /*!< init */ usb_dc_init(); - /* USER CODE END 2 */ + /* USER CODE END 2 */ - /* Infinite loop */ - /* USER CODE BEGIN WHILE */ + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ while (1) { - /* USER CODE END WHILE */ + /* USER CODE END WHILE */ - /* USER CODE BEGIN 3 */ - -#ifdef USB_CDC - /*!< cdc demo test */ - extern void cdc_test(void); - cdc_test(); -#elif defined USB_HID_KEYBOARD - /*!< hid keyboard demo test */ - extern void hid_keyboard_test(void); - hid_keyboard_test(); -#elif defined USB_HID_MOUSE - /*!< hid mouse demo test */ - extern void hid_mouse_test(void); - hid_mouse_test(); -#elif defined USB_HID_CUSTOM - /*!< hid custom demo test */ - extern void hid_custom_test(void); - hid_custom_test(); -#endif + /* USER CODE BEGIN 3 */ + extern void cdc_acm_data_send_with_dtr_test(void); + cdc_acm_data_send_with_dtr_test(); + HAL_Delay(100); } - /* USER CODE END 3 */ + /* USER CODE END 3 */ } /** @@ -169,39 +137,43 @@ int main(void) */ void SystemClock_Config(void) { - RCC_OscInitTypeDef RCC_OscInitStruct = { 0 }; - RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 }; - RCC_PeriphCLKInitTypeDef PeriphClkInit = { 0 }; + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; - /** Initializes the RCC Oscillators according to the specified parameters + /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; - RCC_OscInitStruct.HSEState = RCC_HSE_ON; - RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; - if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { - Error_Handler(); - } - /** Initializes the CPU, AHB and APB buses clocks + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + /** Initializes the CPU, AHB and APB buses clocks */ - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; - if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { - Error_Handler(); - } - PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; - PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5; - if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { - Error_Handler(); - } + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) + { + Error_Handler(); + } + PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; + PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) + { + Error_Handler(); + } } /** @@ -211,27 +183,30 @@ void SystemClock_Config(void) */ static void MX_USART1_UART_Init(void) { - /* USER CODE BEGIN USART1_Init 0 */ - /* USER CODE END USART1_Init 0 */ + /* USER CODE BEGIN USART1_Init 0 */ - /* USER CODE BEGIN USART1_Init 1 */ + /* USER CODE END USART1_Init 0 */ - /* USER CODE END USART1_Init 1 */ - huart1.Instance = USART1; - huart1.Init.BaudRate = 115200; - huart1.Init.WordLength = UART_WORDLENGTH_8B; - huart1.Init.StopBits = UART_STOPBITS_1; - huart1.Init.Parity = UART_PARITY_NONE; - huart1.Init.Mode = UART_MODE_TX_RX; - huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; - huart1.Init.OverSampling = UART_OVERSAMPLING_16; - if (HAL_UART_Init(&huart1) != HAL_OK) { - Error_Handler(); - } - /* USER CODE BEGIN USART1_Init 2 */ + /* USER CODE BEGIN USART1_Init 1 */ + + /* USER CODE END USART1_Init 1 */ + huart1.Instance = USART1; + huart1.Init.BaudRate = 115200; + huart1.Init.WordLength = UART_WORDLENGTH_8B; + huart1.Init.StopBits = UART_STOPBITS_1; + huart1.Init.Parity = UART_PARITY_NONE; + huart1.Init.Mode = UART_MODE_TX_RX; + huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart1.Init.OverSampling = UART_OVERSAMPLING_16; + if (HAL_UART_Init(&huart1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USART1_Init 2 */ + + /* USER CODE END USART1_Init 2 */ - /* USER CODE END USART1_Init 2 */ } /** @@ -241,25 +216,28 @@ static void MX_USART1_UART_Init(void) */ static void MX_USB_PCD_Init(void) { - /* USER CODE BEGIN USB_Init 0 */ - /* USER CODE END USB_Init 0 */ + /* USER CODE BEGIN USB_Init 0 */ - /* USER CODE BEGIN USB_Init 1 */ + /* USER CODE END USB_Init 0 */ - /* USER CODE END USB_Init 1 */ - hpcd_USB_FS.Instance = USB; - hpcd_USB_FS.Init.dev_endpoints = 8; - hpcd_USB_FS.Init.speed = PCD_SPEED_FULL; - hpcd_USB_FS.Init.low_power_enable = DISABLE; - hpcd_USB_FS.Init.lpm_enable = DISABLE; - hpcd_USB_FS.Init.battery_charging_enable = DISABLE; - if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK) { - Error_Handler(); - } - /* USER CODE BEGIN USB_Init 2 */ + /* USER CODE BEGIN USB_Init 1 */ + + /* USER CODE END USB_Init 1 */ + hpcd_USB_FS.Instance = USB; + hpcd_USB_FS.Init.dev_endpoints = 8; + hpcd_USB_FS.Init.speed = PCD_SPEED_FULL; + hpcd_USB_FS.Init.low_power_enable = DISABLE; + hpcd_USB_FS.Init.lpm_enable = DISABLE; + hpcd_USB_FS.Init.battery_charging_enable = DISABLE; + if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USB_Init 2 */ + + /* USER CODE END USB_Init 2 */ - /* USER CODE END USB_Init 2 */ } /** @@ -269,9 +247,11 @@ static void MX_USB_PCD_Init(void) */ static void MX_GPIO_Init(void) { - /* GPIO Ports Clock Enable */ - __HAL_RCC_GPIOD_CLK_ENABLE(); - __HAL_RCC_GPIOA_CLK_ENABLE(); + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + } /* USER CODE BEGIN 4 */ @@ -284,15 +264,15 @@ static void MX_GPIO_Init(void) */ void Error_Handler(void) { - /* USER CODE BEGIN Error_Handler_Debug */ + /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } - /* USER CODE END Error_Handler_Debug */ + /* USER CODE END Error_Handler_Debug */ } -#ifdef USE_FULL_ASSERT +#ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. @@ -302,10 +282,10 @@ void Error_Handler(void) */ void assert_failed(uint8_t *file, uint32_t line) { - /* USER CODE BEGIN 6 */ + /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ - /* USER CODE END 6 */ + /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ diff --git a/demo/stm32/usb_device/stm32f103c8t6/Core/Src/stm32f1xx_it.c b/demo/stm32/usb_device/stm32f103c8t6/Core/Src/stm32f1xx_it.c index b9e6a918..0c1292fc 100644 --- a/demo/stm32/usb_device/stm32f103c8t6/Core/Src/stm32f1xx_it.c +++ b/demo/stm32/usb_device/stm32f103c8t6/Core/Src/stm32f1xx_it.c @@ -204,13 +204,13 @@ void SysTick_Handler(void) */ //void USB_LP_CAN1_RX0_IRQHandler(void) //{ -///* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */ +// /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */ -///* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */ -// HAL_PCD_IRQHandler(&hpcd_USB_FS); -///* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */ +// /* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */ +// HAL_PCD_IRQHandler(&hpcd_USB_FS); +// /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */ -///* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */ +// /* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */ //} /* USER CODE BEGIN 1 */ diff --git a/demo/stm32/usb_device/stm32f103c8t6/MDK-ARM/stm32f103c8t6.uvoptx b/demo/stm32/usb_device/stm32f103c8t6/MDK-ARM/stm32f103c8t6.uvoptx index e074d4cf..ad4d7ddc 100644 --- a/demo/stm32/usb_device/stm32f103c8t6/MDK-ARM/stm32f103c8t6.uvoptx +++ b/demo/stm32/usb_device/stm32f103c8t6/MDK-ARM/stm32f103c8t6.uvoptx @@ -161,7 +161,7 @@ 0 0 0 - ..\example\hid_keyboard\hid_keyboard_init.c + C:\Users\lvjiazhen\Desktop\CherryUSB\demo\stm32\usb_device\stm32f103c8t6\example\hid_keyboard\hid_keyboard_init.c @@ -263,6 +263,18 @@ 0 0 0 + ..\..\..\..\cdc_acm_template.c + cdc_acm_template.c + 0 + 0 + + + 2 + 4 + 1 + 0 + 0 + 0 ../Core/Src/stm32f1xx_it.c stm32f1xx_it.c 0 @@ -270,7 +282,7 @@ 2 - 4 + 5 1 0 0 @@ -290,7 +302,7 @@ 0 3 - 5 + 6 1 0 0 @@ -302,7 +314,7 @@ 3 - 6 + 7 1 0 0 @@ -314,7 +326,7 @@ 3 - 7 + 8 1 0 0 @@ -326,7 +338,7 @@ 3 - 8 + 9 1 0 0 @@ -338,7 +350,7 @@ 3 - 9 + 10 1 0 0 @@ -350,7 +362,7 @@ 3 - 10 + 11 1 0 0 @@ -362,7 +374,7 @@ 3 - 11 + 12 1 0 0 @@ -374,7 +386,7 @@ 3 - 12 + 13 1 0 0 @@ -386,7 +398,7 @@ 3 - 13 + 14 1 0 0 @@ -398,7 +410,7 @@ 3 - 14 + 15 1 0 0 @@ -410,7 +422,7 @@ 3 - 15 + 16 1 0 0 @@ -422,7 +434,7 @@ 3 - 16 + 17 1 0 0 @@ -434,7 +446,7 @@ 3 - 17 + 18 1 0 0 @@ -446,7 +458,7 @@ 3 - 18 + 19 1 0 0 @@ -458,7 +470,7 @@ 3 - 19 + 20 1 0 0 @@ -470,7 +482,7 @@ 3 - 20 + 21 1 0 0 @@ -482,7 +494,7 @@ 3 - 21 + 22 1 0 0 @@ -502,7 +514,7 @@ 0 4 - 22 + 23 1 0 0 @@ -522,7 +534,7 @@ 0 5 - 23 + 24 1 0 0 @@ -534,7 +546,7 @@ 5 - 24 + 25 1 0 0 @@ -544,18 +556,6 @@ 0 0 - - 5 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\..\class\hid\usbd_hid.c - usbd_hid.c - 0 - 0 - 5 26 @@ -563,18 +563,6 @@ 0 0 0 - ..\..\..\..\..\class\msc\usbd_msc.c - usbd_msc.c - 0 - 0 - - - 5 - 27 - 1 - 0 - 0 - 0 ..\..\..\..\..\port\fsdev\usb_dc_fsdev.c usb_dc_fsdev.c 0 @@ -582,74 +570,6 @@ - - example - 1 - 0 - 0 - 0 - - 6 - 28 - 1 - 0 - 0 - 0 - ..\example\cdc\cdc_init.c - cdc_init.c - 0 - 0 - - - 6 - 29 - 1 - 0 - 0 - 0 - ..\example\hid_mouse\hid_mouse_init.c - hid_mouse_init.c - 0 - 0 - - - 6 - 30 - 1 - 0 - 0 - 0 - ..\example\hid_keyboard\hid_keyboard_init.c - hid_keyboard_init.c - 0 - 0 - - - 6 - 31 - 1 - 0 - 0 - 0 - ..\example\hid_custom\hid_custom_init.c - hid_custom_init.c - 0 - 0 - - - 6 - 32 - 1 - 0 - 0 - 0 - ..\example\msc_ram\msc_ram_init.c - msc_ram_init.c - 0 - 0 - - - ::CMSIS 0 diff --git a/demo/stm32/usb_device/stm32f103c8t6/MDK-ARM/stm32f103c8t6.uvprojx b/demo/stm32/usb_device/stm32f103c8t6/MDK-ARM/stm32f103c8t6.uvprojx index 7c411880..541e204d 100644 --- a/demo/stm32/usb_device/stm32f103c8t6/MDK-ARM/stm32f103c8t6.uvprojx +++ b/demo/stm32/usb_device/stm32f103c8t6/MDK-ARM/stm32f103c8t6.uvprojx @@ -340,7 +340,7 @@ USE_HAL_DRIVER,STM32F103xB - ../Core/Inc; ../Drivers/STM32F1xx_HAL_Driver/Inc; ../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy; ../Drivers/CMSIS/Device/ST/STM32F1xx/Include; ../Drivers/CMSIS/Include; ..\..\..\..\..\common; ..\..\..\..\..\core; ..\..\..\..\..\class\cdc; ..\..\..\..\..\class\msc; ..\..\..\..\..\class\hid; ..\example + ../Core/Inc; ../Drivers/STM32F1xx_HAL_Driver/Inc; ../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy; ../Drivers/CMSIS/Device/ST/STM32F1xx/Include; ../Drivers/CMSIS/Include; ..\..\..\..\..\common; ..\..\..\..\..\core; ..\..\..\..\..\class\cdc; ..\..\..\..\..\class\msc; ..\..\..\..\..\class\hid; ..\example @@ -399,6 +399,11 @@ 1 ../Core/Src/main.c + + cdc_acm_template.c + 1 + ..\..\..\..\cdc_acm_template.c + stm32f1xx_it.c 1 @@ -524,16 +529,6 @@ 1 ..\..\..\..\..\class\cdc\usbd_cdc.c - - usbd_hid.c - 1 - ..\..\..\..\..\class\hid\usbd_hid.c - - - usbd_msc.c - 1 - ..\..\..\..\..\class\msc\usbd_msc.c - usb_dc_fsdev.c 1 @@ -541,138 +536,6 @@ - - example - - - cdc_init.c - 1 - ..\example\cdc\cdc_init.c - - - hid_mouse_init.c - 1 - ..\example\hid_mouse\hid_mouse_init.c - - - 2 - 0 - 0 - 0 - 0 - 0 - 2 - 2 - 2 - 2 - 11 - - - 1 - - - - 2 - 0 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 0 - 2 - 2 - 2 - 2 - 2 - 0 - 0 - 2 - 2 - 2 - 2 - 2 - - - - - - - - - - - - hid_keyboard_init.c - 1 - ..\example\hid_keyboard\hid_keyboard_init.c - - - hid_custom_init.c - 1 - ..\example\hid_custom\hid_custom_init.c - - - 2 - 0 - 0 - 0 - 0 - 0 - 2 - 2 - 2 - 2 - 11 - - - 1 - - - - 2 - 0 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 2 - 0 - 2 - 2 - 2 - 2 - 2 - 0 - 0 - 2 - 2 - 2 - 2 - 2 - - - - - - - - - - - - msc_ram_init.c - 1 - ..\example\msc_ram\msc_ram_init.c - - - ::CMSIS diff --git a/demo/stm32/usb_device/stm32f103c8t6/example/example_select.h b/demo/stm32/usb_device/stm32f103c8t6/example/example_select.h deleted file mode 100644 index b424a8f3..00000000 --- a/demo/stm32/usb_device/stm32f103c8t6/example/example_select.h +++ /dev/null @@ -1,18 +0,0 @@ - -/*!< Use macros to select the examples to test */ - -/*!< cdc */ -#define USB_CDC - -/*!< hid keyboard */ -//#define USB_HID_KEYBOARD - -/*!< hid mouse */ -//#define USB_HID_MOUSE - -/*!< hid custom */ -//#define USB_HID_CUSTOM - -/*!< msc ram */ -//#define USB_MSC_RAM - diff --git a/demo/stm32/usb_device/stm32f429igt6/Core/Src/main.c b/demo/stm32/usb_device/stm32f429igt6/Core/Src/main.c index b3d269e9..d55c7cef 100644 --- a/demo/stm32/usb_device/stm32f429igt6/Core/Src/main.c +++ b/demo/stm32/usb_device/stm32f429igt6/Core/Src/main.c @@ -78,7 +78,7 @@ int fputc(int ch, FILE *f) #define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN) const uint8_t cdc_descriptor[] = { - USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x02, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02), /////////////////////////////////////// diff --git a/demo/stm32/usb_device/stm32h743vbt6/Core/Src/main.c b/demo/stm32/usb_device/stm32h743vbt6/Core/Src/main.c index 0fbde191..1cc5e23f 100644 --- a/demo/stm32/usb_device/stm32h743vbt6/Core/Src/main.c +++ b/demo/stm32/usb_device/stm32h743vbt6/Core/Src/main.c @@ -79,7 +79,7 @@ int fputc(int ch, FILE *f) #define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN) const uint8_t cdc_descriptor[] = { - USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x02, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), + USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01), USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 0x02), ///////////////////////////////////////