参考无协议栈例程目录下nRF5_SDK_17.0.2_d674dde\examples\peripheral\usbd_msc的工程

移植到S340工程下需要做以下步聚

  • 在sdk_config.h中加入以下配置
// <h> POWER_ENABLED菜单// <e> NRFX_POWER_ENABLED - nrfx_power - POWER peripheral driver
//==========================================================
#ifndef NRFX_POWER_ENABLED
#define NRFX_POWER_ENABLED 1
#endif
// <o> NRFX_POWER_CONFIG_IRQ_PRIORITY  - Interrupt priority// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7 #ifndef NRFX_POWER_CONFIG_IRQ_PRIORITY
#define NRFX_POWER_CONFIG_IRQ_PRIORITY 6
#endif// <q> NRFX_POWER_CONFIG_DEFAULT_DCDCEN  - The default configuration of main DCDC regulator// <i> This settings means only that components for DCDC regulator are installed and it can be enabled.#ifndef NRFX_POWER_CONFIG_DEFAULT_DCDCEN
#define NRFX_POWER_CONFIG_DEFAULT_DCDCEN 0
#endif// <q> NRFX_POWER_CONFIG_DEFAULT_DCDCENHV  - The default configuration of High Voltage DCDC regulator// <i> This settings means only that components for DCDC regulator are installed and it can be enabled.#ifndef NRFX_POWER_CONFIG_DEFAULT_DCDCENHV
#define NRFX_POWER_CONFIG_DEFAULT_DCDCENHV 0
#endif// </e>// <e> POWER_ENABLED - nrf_drv_power - POWER peripheral driver - legacy layer
//==========================================================
#ifndef POWER_ENABLED
#define POWER_ENABLED 1
#endif
// <o> POWER_CONFIG_IRQ_PRIORITY  - Interrupt priority// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7 #ifndef POWER_CONFIG_IRQ_PRIORITY
#define POWER_CONFIG_IRQ_PRIORITY 6
#endif// <q> POWER_CONFIG_DEFAULT_DCDCEN  - The default configuration of main DCDC regulator// <i> This settings means only that components for DCDC regulator are installed and it can be enabled.#ifndef POWER_CONFIG_DEFAULT_DCDCEN
#define POWER_CONFIG_DEFAULT_DCDCEN 0
#endif// <q> POWER_CONFIG_DEFAULT_DCDCENHV  - The default configuration of High Voltage DCDC regulator// <i> This settings means only that components for DCDC regulator are installed and it can be enabled.#ifndef POWER_CONFIG_DEFAULT_DCDCENHV
#define POWER_CONFIG_DEFAULT_DCDCENHV 0
#endif// </e>// </h>// <h> QSPI菜单配置// <q> NRF_BLOCK_DEV_EMPTY_ENABLED  - nrf_block_dev_empty - Empty block device#ifndef NRF_BLOCK_DEV_EMPTY_ENABLED
#define NRF_BLOCK_DEV_EMPTY_ENABLED 1
#endif// <q> NRF_BLOCK_DEV_QSPI_ENABLED  - nrf_block_dev_qspi - QSPI block device#ifndef NRF_BLOCK_DEV_QSPI_ENABLED
#define NRF_BLOCK_DEV_QSPI_ENABLED 1
#endif// <q> NRF_BLOCK_DEV_RAM_ENABLED  - nrf_block_dev_ram - RAM block device#ifndef NRF_BLOCK_DEV_RAM_ENABLED
#define NRF_BLOCK_DEV_RAM_ENABLED 1
#endif// <e> NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED - Enables logging in the module.
//==========================================================
#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED
#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED 1
#endif
// <o> NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL  - Default Severity level// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug #ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL
#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL 3
#endif// <o> NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL  - Initial severity level if dynamic filtering is enabled// <0=> Off
// <1=> Error
// <2=> Warning
// <3=> Info
// <4=> Debug #ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL
#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL 3
#endif// <o> NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR  - ANSI escape code prefix.// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White #ifndef NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR
#define NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR 0
#endif// <o> NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR  - ANSI escape code prefix.// <0=> Default
// <1=> Black
// <2=> Red
// <3=> Green
// <4=> Yellow
// <5=> Blue
// <6=> Magenta
// <7=> Cyan
// <8=> White #ifndef NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR
#define NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR 0
#endif// </e>// <e> NRFX_QSPI_ENABLED - nrfx_qspi - QSPI peripheral driver
//==========================================================
#ifndef NRFX_QSPI_ENABLED
#define NRFX_QSPI_ENABLED 1
#endif
// <o> NRFX_QSPI_CONFIG_SCK_DELAY - tSHSL, tWHSL and tSHWL in number of 16 MHz periods (62.5 ns).  <0-255> #ifndef NRFX_QSPI_CONFIG_SCK_DELAY
#define NRFX_QSPI_CONFIG_SCK_DELAY 1
#endif// <o> NRFX_QSPI_CONFIG_XIP_OFFSET - Address offset in the external memory for Execute in Place operation.
#ifndef NRFX_QSPI_CONFIG_XIP_OFFSET
#define NRFX_QSPI_CONFIG_XIP_OFFSET 0
#endif// <o> NRFX_QSPI_CONFIG_READOC  - Number of data lines and opcode used for reading.// <0=> FastRead
// <1=> Read2O
// <2=> Read2IO
// <3=> Read4O
// <4=> Read4IO #ifndef NRFX_QSPI_CONFIG_READOC
#define NRFX_QSPI_CONFIG_READOC 0
#endif// <o> NRFX_QSPI_CONFIG_WRITEOC  - Number of data lines and opcode used for writing.// <0=> PP
// <1=> PP2O
// <2=> PP4O
// <3=> PP4IO #ifndef NRFX_QSPI_CONFIG_WRITEOC
#define NRFX_QSPI_CONFIG_WRITEOC 0
#endif// <o> NRFX_QSPI_CONFIG_ADDRMODE  - Addressing mode.// <0=> 24bit
// <1=> 32bit #ifndef NRFX_QSPI_CONFIG_ADDRMODE
#define NRFX_QSPI_CONFIG_ADDRMODE 0
#endif// <o> NRFX_QSPI_CONFIG_MODE  - SPI mode.// <0=> Mode 0
// <1=> Mode 1 #ifndef NRFX_QSPI_CONFIG_MODE
#define NRFX_QSPI_CONFIG_MODE 0
#endif// <o> NRFX_QSPI_CONFIG_FREQUENCY  - Frequency divider.// <0=> 32MHz/1
// <1=> 32MHz/2
// <2=> 32MHz/3
// <3=> 32MHz/4
// <4=> 32MHz/5
// <5=> 32MHz/6
// <6=> 32MHz/7
// <7=> 32MHz/8
// <8=> 32MHz/9
// <9=> 32MHz/10
// <10=> 32MHz/11
// <11=> 32MHz/12
// <12=> 32MHz/13
// <13=> 32MHz/14
// <14=> 32MHz/15
// <15=> 32MHz/16 #ifndef NRFX_QSPI_CONFIG_FREQUENCY
#define NRFX_QSPI_CONFIG_FREQUENCY 0
#endif// <s> NRFX_QSPI_PIN_SCK - SCK pin value.
#ifndef NRFX_QSPI_PIN_SCK
#define NRFX_QSPI_PIN_SCK 29
#endif// <s> NRFX_QSPI_PIN_CSN - CSN pin value.
#ifndef NRFX_QSPI_PIN_CSN
#define NRFX_QSPI_PIN_CSN 2
#endif// <s> NRFX_QSPI_PIN_IO0 - IO0 pin value.
#ifndef NRFX_QSPI_PIN_IO0
#define NRFX_QSPI_PIN_IO0  30
#endif// <s> NRFX_QSPI_PIN_IO1 - IO1 pin value.
#ifndef NRFX_QSPI_PIN_IO1
#define NRFX_QSPI_PIN_IO1 3
#endif// <s> NRFX_QSPI_PIN_IO2 - IO2 pin value.
#ifndef NRFX_QSPI_PIN_IO2
#define NRFX_QSPI_PIN_IO2 47
#endif// <s> NRFX_QSPI_PIN_IO3 - IO3 pin value.
#ifndef NRFX_QSPI_PIN_IO3
#define NRFX_QSPI_PIN_IO3 28
#endif// <o> NRFX_QSPI_CONFIG_IRQ_PRIORITY  - Interrupt priority// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7 #ifndef NRFX_QSPI_CONFIG_IRQ_PRIORITY
#define NRFX_QSPI_CONFIG_IRQ_PRIORITY 6
#endif// </e>// <e> QSPI_ENABLED - nrf_drv_qspi - QSPI peripheral driver - legacy layer
//==========================================================
#ifndef QSPI_ENABLED
#define QSPI_ENABLED 1
#endif
// <o> QSPI_CONFIG_SCK_DELAY - tSHSL, tWHSL and tSHWL in number of 16 MHz periods (62.5 ns).  <0-255> #ifndef QSPI_CONFIG_SCK_DELAY
#define QSPI_CONFIG_SCK_DELAY 1
#endif// <o> QSPI_CONFIG_XIP_OFFSET - Address offset in the external memory for Execute in Place operation.
#ifndef QSPI_CONFIG_XIP_OFFSET
#define QSPI_CONFIG_XIP_OFFSET 0
#endif// <o> QSPI_CONFIG_READOC  - Number of data lines and opcode used for reading.// <0=> FastRead
// <1=> Read2O
// <2=> Read2IO
// <3=> Read4O
// <4=> Read4IO #ifndef QSPI_CONFIG_READOC
#define QSPI_CONFIG_READOC 0
#endif// <o> QSPI_CONFIG_WRITEOC  - Number of data lines and opcode used for writing.// <0=> PP
// <1=> PP2O
// <2=> PP4O
// <3=> PP4IO #ifndef QSPI_CONFIG_WRITEOC
#define QSPI_CONFIG_WRITEOC 0
#endif// <o> QSPI_CONFIG_ADDRMODE  - Addressing mode.// <0=> 24bit
// <1=> 32bit #ifndef QSPI_CONFIG_ADDRMODE
#define QSPI_CONFIG_ADDRMODE 0
#endif// <o> QSPI_CONFIG_MODE  - SPI mode.// <0=> Mode 0
// <1=> Mode 1 #ifndef QSPI_CONFIG_MODE
#define QSPI_CONFIG_MODE 0
#endif// <o> QSPI_CONFIG_FREQUENCY  - Frequency divider.// <0=> 32MHz/1
// <1=> 32MHz/2
// <2=> 32MHz/3
// <3=> 32MHz/4
// <4=> 32MHz/5
// <5=> 32MHz/6
// <6=> 32MHz/7
// <7=> 32MHz/8
// <8=> 32MHz/9
// <9=> 32MHz/10
// <10=> 32MHz/11
// <11=> 32MHz/12
// <12=> 32MHz/13
// <13=> 32MHz/14
// <14=> 32MHz/15
// <15=> 32MHz/16 #ifndef QSPI_CONFIG_FREQUENCY
#define QSPI_CONFIG_FREQUENCY 0
#endif// <s> QSPI_PIN_SCK - SCK pin value.
#ifndef QSPI_PIN_SCK
#define QSPI_PIN_SCK 29
#endif// <s> QSPI_PIN_CSN - CSN pin value.
#ifndef QSPI_PIN_CSN
#define QSPI_PIN_CSN 2
#endif// <s> QSPI_PIN_IO0 - IO0 pin value.
#ifndef QSPI_PIN_IO0
#define QSPI_PIN_IO0 30
#endif// <s> QSPI_PIN_IO1 - IO1 pin value.
#ifndef QSPI_PIN_IO1
#define QSPI_PIN_IO1 3
#endif// <s> QSPI_PIN_IO2 - IO2 pin value.
#ifndef QSPI_PIN_IO2
#define QSPI_PIN_IO2  47
#endif// <s> QSPI_PIN_IO3 - IO3 pin value.
#ifndef QSPI_PIN_IO3
#define QSPI_PIN_IO3 28
#endif// <o> QSPI_CONFIG_IRQ_PRIORITY  - Interrupt priority// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7 #ifndef QSPI_CONFIG_IRQ_PRIORITY
#define QSPI_CONFIG_IRQ_PRIORITY 6
#endif// </e>// </h>// <h> USB菜单配置// <e> NRFX_USBD_ENABLED - nrfx_usbd - USBD peripheral driver
//==========================================================
#ifndef NRFX_USBD_ENABLED
#define NRFX_USBD_ENABLED 1
#endif
// <o> NRFX_USBD_CONFIG_IRQ_PRIORITY  - Interrupt priority// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7 #ifndef NRFX_USBD_CONFIG_IRQ_PRIORITY
#define NRFX_USBD_CONFIG_IRQ_PRIORITY 6
#endif// <o> NRFX_USBD_CONFIG_DMASCHEDULER_MODE  - USBD DMA scheduler working scheme// <0=> Prioritized access
// <1=> Round Robin #ifndef NRFX_USBD_CONFIG_DMASCHEDULER_MODE
#define NRFX_USBD_CONFIG_DMASCHEDULER_MODE 0
#endif// <q> NRFX_USBD_CONFIG_DMASCHEDULER_ISO_BOOST  - Give priority to isochronous transfers// <i> This option gives priority to isochronous transfers.
// <i> Enabling it assures that isochronous transfers are always processed,
// <i> even if multiple other transfers are pending.
// <i> Isochronous endpoints are prioritized before the usbd_dma_scheduler_algorithm
// <i> function is called, so the option is independent of the algorithm chosen.#ifndef NRFX_USBD_CONFIG_DMASCHEDULER_ISO_BOOST
#define NRFX_USBD_CONFIG_DMASCHEDULER_ISO_BOOST 1
#endif// <q> NRFX_USBD_CONFIG_ISO_IN_ZLP  - Respond to an IN token on ISO IN endpoint with ZLP when no data is ready// <i> If set, ISO IN endpoint will respond to an IN token with ZLP when no data is ready to be sent.
// <i> Else, there will be no response.#ifndef NRFX_USBD_CONFIG_ISO_IN_ZLP
#define NRFX_USBD_CONFIG_ISO_IN_ZLP 0
#endif// <q> NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211  - Use workaround for anomaly 211// <i> If set, workaround for anomaly 211 will be enabled.
// <i> Anomaly 211 - Device remains in SUSPEND too long when host resumes
// <i> bus activity (sending SOF packets) without a RESUME condition.#ifndef NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211
#define NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211 0
#endif// </e>// <e> USBD_ENABLED - nrf_drv_usbd - Software Component
//==========================================================
#ifndef USBD_ENABLED
#define USBD_ENABLED 1
#endif
// <o> USBD_CONFIG_IRQ_PRIORITY  - Interrupt priority// <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6
// <7=> 7 #ifndef USBD_CONFIG_IRQ_PRIORITY
#define USBD_CONFIG_IRQ_PRIORITY 6
#endif// <o> USBD_CONFIG_DMASCHEDULER_MODE  - USBD SMA scheduler working scheme// <0=> Prioritized access
// <1=> Round Robin #ifndef USBD_CONFIG_DMASCHEDULER_MODE
#define USBD_CONFIG_DMASCHEDULER_MODE 0
#endif// <q> USBD_CONFIG_DMASCHEDULER_ISO_BOOST  - Give priority to isochronous transfers// <i> This option gives priority to isochronous transfers.
// <i> Enabling it assures that isochronous transfers are always processed,
// <i> even if multiple other transfers are pending.
// <i> Isochronous endpoints are prioritized before the usbd_dma_scheduler_algorithm
// <i> function is called, so the option is independent of the algorithm chosen.#ifndef USBD_CONFIG_DMASCHEDULER_ISO_BOOST
#define USBD_CONFIG_DMASCHEDULER_ISO_BOOST 1
#endif// <q> USBD_CONFIG_ISO_IN_ZLP  - Respond to an IN token on ISO IN endpoint with ZLP when no data is ready// <i> If set, ISO IN endpoint will respond to an IN token with ZLP when no data is ready to be sent.
// <i> Else, there will be no response.
// <i> NOTE: This option does not work on Engineering A chip.#ifndef USBD_CONFIG_ISO_IN_ZLP
#define USBD_CONFIG_ISO_IN_ZLP 0
#endif// </e>// <e> APP_USBD_ENABLED - app_usbd - USB Device library
//==========================================================
#ifndef APP_USBD_ENABLED
#define APP_USBD_ENABLED 1
#endif
// <s> APP_USBD_VID - Vendor ID.// <i> Note: This value is not editable in Configuration Wizard.
// <i> Vendor ID ordered from USB IF: http://www.usb.org/developers/vendor/
#ifndef APP_USBD_VID
#define APP_USBD_VID 0x1915
#endif// <s> APP_USBD_PID - Product ID.// <i> Note: This value is not editable in Configuration Wizard.
// <i> Selected Product ID
#ifndef APP_USBD_PID
#define APP_USBD_PID 0x520D
#endif// <o> APP_USBD_DEVICE_VER_MAJOR - Major device version  <0-99> // <i> Major device version, will be converted automatically to BCD notation. Use just decimal values.#ifndef APP_USBD_DEVICE_VER_MAJOR
#define APP_USBD_DEVICE_VER_MAJOR 1
#endif// <o> APP_USBD_DEVICE_VER_MINOR - Minor device version  <0-9> // <i> Minor device version, will be converted automatically to BCD notation. Use just decimal values.#ifndef APP_USBD_DEVICE_VER_MINOR
#define APP_USBD_DEVICE_VER_MINOR 0
#endif// <o> APP_USBD_DEVICE_VER_SUB - Sub-minor device version  <0-9> // <i> Sub-minor device version, will be converted automatically to BCD notation. Use just decimal values.#ifndef APP_USBD_DEVICE_VER_SUB
#define APP_USBD_DEVICE_VER_SUB 0
#endif// <q> APP_USBD_CONFIG_SELF_POWERED  - Self-powered device, as opposed to bus-powered.#ifndef APP_USBD_CONFIG_SELF_POWERED
#define APP_USBD_CONFIG_SELF_POWERED 1
#endif// <o> APP_USBD_CONFIG_MAX_POWER - MaxPower field in configuration descriptor in milliamps.  <0-500> #ifndef APP_USBD_CONFIG_MAX_POWER
#define APP_USBD_CONFIG_MAX_POWER 100
#endif// <q> APP_USBD_CONFIG_POWER_EVENTS_PROCESS  - Process power events.// <i> Enable processing power events in USB event handler.#ifndef APP_USBD_CONFIG_POWER_EVENTS_PROCESS
#define APP_USBD_CONFIG_POWER_EVENTS_PROCESS 1
#endif// <e> APP_USBD_CONFIG_EVENT_QUEUE_ENABLE - Enable event queue.// <i> This is the default configuration when all the events are placed into internal queue.
// <i> Disable it when an external queue is used like app_scheduler or if you wish to process all events inside interrupts.
// <i> Processing all events from the interrupt level adds requirement not to call any functions that modifies the USBD library state from the context higher than USB interrupt context.
// <i> Functions that modify USBD state are functions for sleep, wakeup, start, stop, enable, and disable.
//==========================================================
#ifndef APP_USBD_CONFIG_EVENT_QUEUE_ENABLE
#define APP_USBD_CONFIG_EVENT_QUEUE_ENABLE 1
#endif
// <o> APP_USBD_CONFIG_EVENT_QUEUE_SIZE - The size of the event queue.  <16-64> // <i> The size of the queue for the events that would be processed in the main loop.#ifndef APP_USBD_CONFIG_EVENT_QUEUE_SIZE
#define APP_USBD_CONFIG_EVENT_QUEUE_SIZE 32
#endif// <o> APP_USBD_CONFIG_SOF_HANDLING_MODE  - Change SOF events handling mode.// <i> Normal queue   - SOF events are pushed normally into the event queue.
// <i> Compress queue - SOF events are counted and binded with other events or executed when the queue is empty.
// <i>                  This prevents the queue from filling up with SOF events.
// <i> Interrupt      - SOF events are processed in interrupt.
// <0=> Normal queue
// <1=> Compress queue
// <2=> Interrupt #ifndef APP_USBD_CONFIG_SOF_HANDLING_MODE
#define APP_USBD_CONFIG_SOF_HANDLING_MODE 1
#endif// </e>// <q> APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE  - Provide a function that generates timestamps for logs based on the current SOF.// <i> The function app_usbd_sof_timestamp_get is implemented if the logger is enabled.
// <i> Use it when initializing the logger.
// <i> SOF processing is always enabled when this configuration parameter is active.
// <i> Note: This option is configured outside of APP_USBD_CONFIG_LOG_ENABLED.
// <i> This means that it works even if the logging in this very module is disabled. #ifndef APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE
#define APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE 1
#endif// <o> APP_USBD_CONFIG_DESC_STRING_SIZE - Maximum size of the NULL-terminated string of the string descriptor.  <31-254> // <i> 31 characters can be stored in the internal USB buffer used for transfers.
// <i> Any value higher than 31 creates an additional buffer just for descriptor strings.#ifndef APP_USBD_CONFIG_DESC_STRING_SIZE
#define APP_USBD_CONFIG_DESC_STRING_SIZE 31
#endif// <q> APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED  - Enable UTF8 conversion.// <i> Enable UTF8-encoded characters. In normal processing, only ASCII characters are available.#ifndef APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED
#define APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED 0
#endif// <s> APP_USBD_STRINGS_LANGIDS - Supported languages identifiers.// <i> Note: This value is not editable in Configuration Wizard.
// <i> Comma-separated list of supported languages.
#ifndef APP_USBD_STRINGS_LANGIDS
#define APP_USBD_STRINGS_LANGIDS APP_USBD_LANG_AND_SUBLANG(APP_USBD_LANG_ENGLISH, APP_USBD_SUBLANG_ENGLISH_US)
#endif// <e> APP_USBD_STRING_ID_MANUFACTURER - Define manufacturer string ID.// <i> Setting ID to 0 disables the string.
//==========================================================
#ifndef APP_USBD_STRING_ID_MANUFACTURER
#define APP_USBD_STRING_ID_MANUFACTURER 1
#endif
// <q> APP_USBD_STRINGS_MANUFACTURER_EXTERN  - Define whether @ref APP_USBD_STRINGS_MANUFACTURER is created by macro or declared as a global variable.#ifndef APP_USBD_STRINGS_MANUFACTURER_EXTERN
#define APP_USBD_STRINGS_MANUFACTURER_EXTERN 0
#endif// <s> APP_USBD_STRINGS_MANUFACTURER - String descriptor for the manufacturer name.// <i> Note: This value is not editable in Configuration Wizard.
// <i> Comma-separated list of manufacturer names for each defined language.
// <i> Use @ref APP_USBD_STRING_DESC macro to create string descriptor from a NULL-terminated string.
// <i> Use @ref APP_USBD_STRING_RAW8_DESC macro to create string descriptor from comma-separated uint8_t values.
// <i> Use @ref APP_USBD_STRING_RAW16_DESC macro to create string descriptor from comma-separated uint16_t values.
// <i> Alternatively, configure the macro to point to any internal variable pointer that already contains the descriptor.
// <i> Setting string to NULL disables that string.
// <i> The order of manufacturer names must be the same like in @ref APP_USBD_STRINGS_LANGIDS.
#ifndef APP_USBD_STRINGS_MANUFACTURER
#define APP_USBD_STRINGS_MANUFACTURER APP_USBD_STRING_DESC("Nordic Semiconductor")
#endif// </e>// <e> APP_USBD_STRING_ID_PRODUCT - Define product string ID.// <i> Setting ID to 0 disables the string.
//==========================================================
#ifndef APP_USBD_STRING_ID_PRODUCT
#define APP_USBD_STRING_ID_PRODUCT 2
#endif
// <q> APP_USBD_STRINGS_PRODUCT_EXTERN  - Define whether @ref APP_USBD_STRINGS_PRODUCT is created by macro or declared as a global variable.#ifndef APP_USBD_STRINGS_PRODUCT_EXTERN
#define APP_USBD_STRINGS_PRODUCT_EXTERN 0
#endif// <s> APP_USBD_STRINGS_PRODUCT - String descriptor for the product name.// <i> Note: This value is not editable in Configuration Wizard.
// <i> List of product names that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER.
#ifndef APP_USBD_STRINGS_PRODUCT
#define APP_USBD_STRINGS_PRODUCT APP_USBD_STRING_DESC("nRF52 USB MSC Demo")
#endif// </e>// <e> APP_USBD_STRING_ID_SERIAL - Define serial number string ID.// <i> Setting ID to 0 disables the string.
//==========================================================
#ifndef APP_USBD_STRING_ID_SERIAL
#define APP_USBD_STRING_ID_SERIAL 3
#endif
// <q> APP_USBD_STRING_SERIAL_EXTERN  - Define whether @ref APP_USBD_STRING_SERIAL is created by macro or declared as a global variable.#ifndef APP_USBD_STRING_SERIAL_EXTERN
#define APP_USBD_STRING_SERIAL_EXTERN 1
#endif// <s> APP_USBD_STRING_SERIAL - String descriptor for the serial number.// <i> Note: This value is not editable in Configuration Wizard.
// <i> Serial number that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER.
#ifndef APP_USBD_STRING_SERIAL
#define APP_USBD_STRING_SERIAL g_extern_serial_number
#endif// </e>// <e> APP_USBD_STRING_ID_CONFIGURATION - Define configuration string ID.// <i> Setting ID to 0 disables the string.
//==========================================================
#ifndef APP_USBD_STRING_ID_CONFIGURATION
#define APP_USBD_STRING_ID_CONFIGURATION 4
#endif
// <q> APP_USBD_STRING_CONFIGURATION_EXTERN  - Define whether @ref APP_USBD_STRINGS_CONFIGURATION is created by macro or declared as global variable.#ifndef APP_USBD_STRING_CONFIGURATION_EXTERN
#define APP_USBD_STRING_CONFIGURATION_EXTERN 0
#endif// <s> APP_USBD_STRINGS_CONFIGURATION - String descriptor for the device configuration.// <i> Note: This value is not editable in Configuration Wizard.
// <i> Configuration string that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER.
#ifndef APP_USBD_STRINGS_CONFIGURATION
#define APP_USBD_STRINGS_CONFIGURATION APP_USBD_STRING_DESC("Default configuration")
#endif// </e>// <s> APP_USBD_STRINGS_USER - Default values for user strings.// <i> Note: This value is not editable in Configuration Wizard.
// <i> This value stores all application specific user strings with the default initialization.
// <i> The setup is done by X-macros.
// <i> Expected macro parameters:
// <i> @code
// <i> X(mnemonic, [=str_idx], ...)
// <i> @endcode
// <i> - @c mnemonic: Mnemonic of the string descriptor that would be added to
// <i>                @ref app_usbd_string_desc_idx_t enumerator.
// <i> - @c str_idx : String index value, can be set or left empty.
// <i>                For example, WinUSB driver requires descriptor to be present on 0xEE index.
// <i>                Then use X(USBD_STRING_WINUSB, =0xEE, (APP_USBD_STRING_DESC(...)))
// <i> - @c ...     : List of string descriptors for each defined language.
#ifndef APP_USBD_STRINGS_USER
#define APP_USBD_STRINGS_USER X(APP_USER_1, , APP_USBD_STRING_DESC("User 1"))
#endif// </e>// <q> APP_USBD_MSC_ENABLED  - app_usbd_msc - USB MSC class#ifndef APP_USBD_MSC_ENABLED
#define APP_USBD_MSC_ENABLED 1
#endif
// </h>
  • 加入以下文件到工程


  • sdk_config.h中修改QSPI引脚及频率为32MHz
  • nrf_serial_flash_params.c中修改flash的ID及容量,根据flash的规格描述来修改,以下为0xA1, 0x28, 0x18的ID及16MB容量的flash
static const nrf_serial_flash_params_t m_sflash_params[] = {{    /*MXIC MX25R6435F*/.read_id = { 0xA1, 0x28, 0x18 },.capabilities = 0x00,.size = 16 * 1024 * 1024,.erase_size = 4 * 1024,.program_size = 256,}
};
  • U盘函数文件
#ifndef __BSP_USBD_CORE_H
#define __BSP_USBD_CORE_H#include "nrf_drv_usbd.h"
#include "ff.h"
#include "diskio_blkdev.h"
#include "app_usbd.h"
#include "app_usbd_core.h"
#include "app_usbd_string_desc.h"
#include "app_usbd_msc.h"
#include "nrf_block_dev_qspi.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_power.h"
#include "app_usbd_serial_num.h"#ifdef __cplusplus
extern "C" {#endifvoid usbd_evt_process(void);
void usbd_initialization(void);#ifdef __cplusplus
}
#endif#endif
#include "BSP_USBD_core.h"
#include "nrf_delay.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"#define NRF_LOG_MODULE_NAME usbd_core
#define NRF_LOG_LEVEL       3
#define NRF_LOG_INFO_COLOR  4
#define NRF_LOG_DEBUG_COLOR 3
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();/*** @brief Enable power USB detection** Configure if example supports USB port connection*/
#ifndef USBD_POWER_DETECTION
#define USBD_POWER_DETECTION true
#endif/*** @brief FatFS for QPSI enable/disable*/
#define USE_FATFS_QSPI    1/*** @brief Mass storage class user event handler*/
static void msc_user_ev_handler(app_usbd_class_inst_t const * p_inst,app_usbd_msc_user_event_t     event);/*** @brief  QSPI block device definition*/
NRF_BLOCK_DEV_QSPI_DEFINE(m_block_dev_qspi,NRF_BLOCK_DEV_QSPI_CONFIG(512,NRF_BLOCK_DEV_QSPI_FLAG_CACHE_WRITEBACK,NRF_DRV_QSPI_DEFAULT_CONFIG),NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "QSPI", "1.00")
);#define BLOCKDEV_LIST() (                                   \NRF_BLOCKDEV_BASE_ADDR(m_block_dev_qspi, block_dev),     \
)/*** @brief Endpoint list passed to @ref APP_USBD_MSC_GLOBAL_DEF*/
#define ENDPOINT_LIST() APP_USBD_MSC_ENDPOINT_LIST(1, 1)/*** @brief Mass storage class work buffer size*/
#define MSC_WORKBUFFER_SIZE (1024)/*lint -save -e26 -e64 -e123 -e505 -e651*/
/*** @brief Mass storage class instance*/
APP_USBD_MSC_GLOBAL_DEF(m_app_msc,0,msc_user_ev_handler,ENDPOINT_LIST(),BLOCKDEV_LIST(),MSC_WORKBUFFER_SIZE);/*** @brief  USB connection status*/
static bool m_usb_connected = false;#if USE_FATFS_QSPIstatic bool fatfs_init(void)
{FRESULT ff_result;DSTATUS disk_state = STA_NOINIT;memset(&m_filesystem, 0, sizeof(FATFS));// Initialize FATFS disk I/O interface by providing the block device.static diskio_blkdev_t drives[] ={DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_qspi, block_dev), NULL)};diskio_blockdev_register(drives, ARRAY_SIZE(drives));NRF_LOG_INFO("Initializing disk 0 (QSPI)...");disk_state = disk_initialize(0);if (disk_state){NRF_LOG_INFO("Disk initialization failed.");return false;}NRF_LOG_INFO("Mounting volume...");ff_result = f_mount(&m_filesystem, "", 1);if (ff_result != FR_OK){if (ff_result == FR_NO_FILESYSTEM){uint8_t work[_MAX_SS]; /* Work area (larger is better for process time) */ff_result=f_mkfs("",FM_FAT|FM_SFD,1024,work,sizeof work);//格式化FLASH,1,盘符;1,不需要引导区,8个扇区为1个簇if(ff_result==0){f_setlabel((const TCHAR *)"NORDIC U"); //设置Flash磁盘的名字为:NORDIC UNRF_LOG_INFO("set disk name");}else{NRF_LOG_INFO("format fail");}   //格式化失败}else{NRF_LOG_INFO("Mount failed: %u", ff_result);}return false;}return true;
}
static void fatfs_mkfs(void)
{FRESULT ff_result;if (m_usb_connected){NRF_LOG_ERROR("Unable to operate on filesystem while USB is connected");return;}NRF_LOG_INFO("\r\nCreating filesystem...");static uint8_t buf[512];ff_result = f_mkfs("", FM_FAT, 1024, buf, sizeof(buf));if (ff_result != FR_OK){NRF_LOG_ERROR("Mkfs failed.");return;}NRF_LOG_INFO("Mounting volume...");ff_result = f_mount(&m_filesystem, "", 1);if (ff_result != FR_OK){NRF_LOG_ERROR("Mount failed.");return;}NRF_LOG_INFO("Done");
}static void fatfs_ls(void)
{DIR dir;FRESULT ff_result;FILINFO fno;if (m_usb_connected){NRF_LOG_ERROR("Unable to operate on filesystem while USB is connected");return;}NRF_LOG_INFO("\r\nListing directory: /");ff_result = f_opendir(&dir, "/");if (ff_result != FR_OK){NRF_LOG_ERROR("Directory listing failed: %u", ff_result);return;}uint32_t entries_count = 0;do{ff_result = f_readdir(&dir, &fno);if (ff_result != FR_OK){NRF_LOG_ERROR("Directory read failed: %u", ff_result);return;}if (fno.fname[0]){if (fno.fattrib & AM_DIR){NRF_LOG_RAW_INFO("   <DIR>   %s\r\n",(uint32_t)fno.fname);}else{NRF_LOG_RAW_INFO("%9lu  %s\r\n", fno.fsize, (uint32_t)fno.fname);}}++entries_count;NRF_LOG_FLUSH();} while (fno.fname[0]);NRF_LOG_RAW_INFO("Entries count: %u\r\n", entries_count);
}static void fatfs_file_create(void)
{FRESULT ff_result;FIL file;char filename[16];if (m_usb_connected){NRF_LOG_ERROR("Unable to operate on filesystem while USB is connected");return;}(void)snprintf(filename, sizeof(filename), "%s.txt", "dev_id");NRF_LOG_RAW_INFO("Creating random file: %s ...", (uint32_t)filename);NRF_LOG_FLUSH();ff_result = f_open(&file, filename, FA_OPEN_ALWAYS | FA_WRITE);if (ff_result != FR_OK){NRF_LOG_INFO("\r\nUnable to open or create file: %u", ff_result);NRF_LOG_FLUSH();return;}if(f_size(&file) == 0){uint32_t id = 1;uint32_t len;ff_result = f_write(&file,&id,sizeof(uint32_t),&len);if(ff_result != FR_OK){NRF_LOG_ERROR("\r\nUnable to write file: %u", ff_result);}}NRF_LOG_INFO("\r\nfile size: %u", f_size(&file));ff_result = f_close(&file);if (ff_result != FR_OK){NRF_LOG_ERROR("\r\nUnable to close file: %u", ff_result);NRF_LOG_FLUSH();return;}NRF_LOG_RAW_INFO("done\r\n");
}static void fatfs_uninit(void)
{NRF_LOG_INFO("Un-initializing disk 0 (QSPI)...");UNUSED_RETURN_VALUE(disk_uninitialize(0));
}
#else //USE_FATFS_QSPI
#define fatfs_init()        false
#define fatfs_mkfs()        do { } while (0)
#define fatfs_ls()          do { } while (0)
#define fatfs_file_create() do { } while (0)
#define fatfs_uninit()      do { } while (0)
#endif/*** @brief Class specific event handler.** @param p_inst    Class instance.* @param event     Class specific event.*/
static void msc_user_ev_handler(app_usbd_class_inst_t const * p_inst,app_usbd_msc_user_event_t     event)
{UNUSED_PARAMETER(p_inst);UNUSED_PARAMETER(event);}/*** @brief USBD library specific event handler.** @param event     USBD library event.*/
static void usbd_user_ev_handler(app_usbd_event_type_t event)
{switch (event){case APP_USBD_EVT_DRV_SUSPEND:NRF_LOG_INFO("APP_USBD_EVT_DRV_SUSPEND");break;case APP_USBD_EVT_DRV_RESUME:NRF_LOG_INFO("APP_USBD_EVT_DRV_RESUME");break;case APP_USBD_EVT_STARTED:NRF_LOG_INFO("APP_USBD_EVT_STARTED");break;case APP_USBD_EVT_STOPPED:UNUSED_RETURN_VALUE(fatfs_init());app_usbd_disable();NRF_LOG_INFO("APP_USBD_EVT_STOPPED");break;case APP_USBD_EVT_POWER_DETECTED:NRF_LOG_INFO("USB power detected");if (!nrf_drv_usbd_is_enabled()){fatfs_uninit();app_usbd_enable();}break;case APP_USBD_EVT_POWER_REMOVED:NRF_LOG_INFO("USB power removed");app_usbd_stop();m_usb_connected = false;break;case APP_USBD_EVT_POWER_READY:NRF_LOG_INFO("USB ready");app_usbd_start();m_usb_connected = true;break;default:break;}}/**
* @brieaf usbd事件处理
*/
void usbd_evt_process(void)
{while (app_usbd_event_queue_process()){/* Nothing to do */}
}static volatile bool m_finished = false;
static void qspi_handler(nrf_drv_qspi_evt_t event, void * p_context)
{UNUSED_PARAMETER(event);UNUSED_PARAMETER(p_context);m_finished = true;
}FRESULT get_memory_space(uint32_t * total_p, uint32_t * free_p)
{FRESULT result;DWORD fre_clust = 0;uint32_t fre_sect = 0;uint32_t tot_sect = 0;FATFS fs;FATFS *fs1 = &fs;result = f_getfree((const TCHAR*)"/",&fre_clust,&fs1);if(result == 0){tot_sect = (fs1->n_fatent-2)*fs1->csize; // total sectorfre_sect = fre_clust * fs1->csize;
#if _MAX_SS != 512tot_sect*=fs1->ssize/512;tot_sect*=fs1->ssize/512;
#endif*total_p = tot_sect >> 1;  // unit in kb*free_p = fre_sect >> 1;   // unit in kb}return result;}/**
* @brieaf USB初时化
*/
void usbd_initialization(void)
{ret_code_t ret;static const app_usbd_config_t usbd_config = {.ev_state_proc = usbd_user_ev_handler};app_usbd_serial_num_generate();if (fatfs_init()){NRF_LOG_INFO("================> fatfs_init");fatfs_ls();fatfs_file_create();}ret = app_usbd_init(&usbd_config);APP_ERROR_CHECK(ret);app_usbd_class_inst_t const * class_inst_msc = app_usbd_msc_class_inst_get(&m_app_msc);ret = app_usbd_class_append(class_inst_msc);APP_ERROR_CHECK(ret);NRF_LOG_INFO("USBD MSC example started.");if (USBD_POWER_DETECTION){ret = app_usbd_power_events_enable();APP_ERROR_CHECK(ret);}else{NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now");app_usbd_enable();app_usbd_start();m_usb_connected = true;}uint32_t total,free;get_memory_space(&total,&free);NRF_LOG_INFO("total %d,free %d",total,free);}
  • 在softdevice_setup函数中加入nrf_drv_power_init初时化
/**@brief BLE + ANT stack initialization.** @details Initializes the SoftDevice and the stack event interrupt.*/
static void softdevice_setup(void)
{#if NRF_MODULE_ENABLED(POWER)ret_code_t ret = nrf_drv_power_init(NULL);APP_ERROR_CHECK(ret);
#endifret_code_t err_code = nrf_sdh_enable_request();APP_ERROR_CHECK(err_code);ASSERT(nrf_sdh_is_enabled());// Configure the BLE stack using the default settings.// Fetch the start address of the application RAM.uint32_t ram_start = 0;err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);APP_ERROR_CHECK(err_code);// Enable BLE stack.err_code = nrf_sdh_ble_enable(&ram_start);APP_ERROR_CHECK(err_code);err_code = nrf_sdh_ant_enable();APP_ERROR_CHECK(err_code);err_code = ant_plus_key_set(ANTPLUS_NETWORK_NUMBER);APP_ERROR_CHECK(err_code);// Register a handler for BLE events.NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
#if ANT_HRM_ENABLEDNRF_SDH_ANT_OBSERVER(m_ant_observer, APP_ANT_OBSERVER_PRIO, ant_evt_handler, NULL);
#endif}
  • 在ffconf.h文件中打开磁盘名称设置功能
#define _USE_LABEL       1
  • 在fatfs_init
  • main.c中进入主循环前调用usbd_initialization函数
  usbd_initialization();
  • 在main.c主循环中调用 usbd_evt_process函数
 usbd_evt_process();
  • 编译运行,并插入到电脑

  • 调用get_memory_space获取存储空间信息
     uint32_t total,free;get_memory_space(&total,&free);NRF_LOG_INFO("total %d,free %d",total,free);

<00> info> usbd_core: total 16335,free 16333

基于52840 S340协议栈USB flash U盘实现相关推荐

  1. STM32CubeMX | STM32基于HAL实现USB模拟U盘

    STM32CubeMX | STM32基于HAL实现USB模拟U盘 目录 STM32CubeMX | STM32基于HAL实现USB模拟U盘 (1)工程配置 (2)代码修改 环境说明: win10 S ...

  2. 基于闪存存储原理的U盘数据安全测试和U盘数据保护软件

    第一章 摘要 Flash Memory是一种长寿命的非易失性存储介质,其存储原理存在诸多漏洞.其中最为严重的则为写入次数上限.而以闪存作为存储介质的U盘是否会因闪存的存储缺陷而成为不安全的存储设备,这 ...

  3. RT-thread实现USB虚拟U盘 模拟读卡器读写sd0

    前言 rt-thread的usb组件包含了usb-device.usb-host等,最近需要在项目中添加PC端读写SD的功能,于是便考虑使用到本项目中去,这里我选用了usb-device,可以给USB ...

  4. bios 闪存颗粒_使用USB闪存盘从失败的BIOS刷新中恢复HP Compaq BIOS危机

    bios 闪存颗粒 I tried to flash my HP Compaq CQ35-240TX's BIOS to F.15 but unfortunately failed. The comp ...

  5. 基于CH375的嵌入式USB文件加解密系统的设计

    基于CH375的嵌入式USB文件加解密系统的设计 [日期:2008-7-21] 来源:电子技术应用  作者:华中科技大学 电子与信息工程系, 湖北 武汉 430074 [字体:大 中 小] <s ...

  6. linux mic阵列通道丢数据,基于XMOS平台的USB麦克风阵列多声道采集装置

    技术领域 本实用新型涉及麦克风阵列多声道声音采集领域,尤其涉及基于XMOS平台的USB麦克风阵列多声道采集装置. 背景技术 麦克风阵列(Array Microphone),是由2个以上数量的声学数字或 ...

  7. 嵌入式linux作为hid设备,基于嵌入式系统的USB(HID)设备

    基于嵌入式系统的USB(HID)设备 目前嵌入式系统在数字化电子产品领域应用越来越广泛.随着其成本的降低,大有取代单片机的趋势. USB设备以其小巧.便携.即插即用.成本低廉等优势在当前的桌面应用中有 ...

  8. 简单实现stm32f103芯片usb模拟U盘进行IAP更新用户程序

    更新单片机内的用户程序,方式一般都是仿真器,串口,网络口,usb DFU,另类一点CAN也行,但是这些方式都有一个共同点,必须要有相应的上位机配合操作,还要教会别人使用,那么能不能有更简单傻瓜化的升级 ...

  9. ecs服务器配置git_基于ECS和NAS搭建个人网盘

    场景介绍 本文为您介绍如何快速搭建一个基于ECS和NAS的私有网盘. 背景知识 本场景主要涉及以下云产品和服务: 云服务器ECS 云服务器(Elastic Compute Service,简称ECS) ...

最新文章

  1. android定义空字符串数组,android – retrofit:处理可以是空字符串或数组的属性
  2. 寄存器和常用的汇编指令
  3. Centos7 修改SSH 端口
  4. Security-OAuth2.0 密码模式之客户端实现
  5. Delphi中判断控件的详细类型
  6. 【数据竞赛】Kaggle实战之特征工程篇-20大文本特征(下)
  7. c语言编程输出数组元素之和,C语言 输出一个数组中,所有元素之和为0的子序列...
  8. kotlin的loop和Range、list和map
  9. Tensorflow CUDA及CUDNN版本对应关系表查询
  10. Atitit.常见的异常分类 目录 1. 双元分类法 1 1.1. 按照语言分 java js c# php等 1 1.2. 通用常见异常vs 特定异常 1 1.3. Runtime ex vs c
  11. Mysql 时间戳类型使用心得
  12. 机器视觉详解及入门必看
  13. 用这些进行PDF翻译,双语对照、翻译后排版不变、还免费!
  14. POJ-1637 混合图欧拉回路-网络流求解
  15. vue,videojs实现hls直播(萤石视频回放)
  16. 用ssm进行微信开发,实现微信登录验证功能
  17. C语言开发必会 宏定义、宏函数
  18. 堡垒机-百百堡垒机-基于WEB的VNC、RDP、SSH远程控制。无须任何插件,随时随地远程。
  19. 机器人视觉分析算法_机器视觉处理:目标检测和跟踪
  20. java.awt包_Java中awt包

热门文章

  1. html当作附件发送,邮件作为附件怎么发 怎样把邮件作为附件来进行传送?
  2. MES管理系统中,生产调度业务流程是怎么样的
  3. Spring框架学习路线
  4. 成功将 戴尔灵越燃7000 II 改装Win7
  5. jenkins2.3031 出现“Error 403 No valid crumb was included in the request ”的解决方案
  6. 广告图片自动轮播控件
  7. 我为什么而活着 [英]罗素
  8. 网络能力认证CCSC-管理1级 技术1级别
  9. 数据分析: kaggle比赛 - 销量预测
  10. java基于springboot在线小说阅读网站