mmWave SDK Module Documentation--Millimeter Wave(mmw) Demo for XWR18XX

本文介绍了一款使用mmWave SDK的毫米波雷达Demo,详细解释了其系统执行流程、数据路径处理、输出信息及硬件资源分配等内容。文章还探讨了LVDS流特性及其实施注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Introduction

在这里插入图片描述
毫米波demo使用mmWave SDK(软件开发工具包)中的驱动程序演示了XWR18xxSoC的一些功能,它允许用户指定线性调频脉冲的配置文件,并实时显示检测到的对象和其他信息
下面是这个demo特征的高级演示功能:

  1. 能够通过命令行接口(CLI)或通过TI Gallery App(mmWave Demo Visualizer)指定特定的线性调频配置文件,mmWave Demo Visualizer允许用户通过UART的输入端口提供各种配置文件和从另一个UART端口进行实时检测的输出的显示
  2. 在demo目录下的一些简单的配置文件可以与CLI一起使用或者是通过mmWave demo Visualizer使用:mmw/profiles
  3. 对被检测的物体进行1D、2D、CFAR、方位角和仰角处理,实时输出被测物体的速度和三个空间坐标(x、y、z)。该演示还可以配置为只进行2D检测(速度和x、y坐标)
  4. 除了像方位热图和多普勒距离热图的目标检测之外,还有各种各样的显示选项

Limitations

  1. 由于UART的速度限制(<1 Mbps),因此帧时间限制更严格。例如,对于方位角和多普勒热图的256FFT距离和16点FFT多普勒,它需要大约200毫秒的传输
  2. 对于大多数开发板来说,观测到的距离偏差只有几厘米。用户可以在他们的估计距离偏差,并使用在距离偏差和Rx通道增益/相位测量和补偿中描述的校准程序进行校正

System Execution Flow

毫米波演示运行在R4F(MSS)和DSP(DSS)。下图显示了系统的执行流程:
在这里插入图片描述

Software Tasks

demo由以下(SYSBIOS)任务组成:

MSS

  1. MmwDemo_initTask。这个任务是由main创建和运行并且是一次活动性任务,其主要功能是初始化驱动(<driver>_init),MMwave模块(MMwave_init),DPM模块(DPM_init),打开UART和数据路径相关的驱动(ADCBUF), 并且创建以下的任务(CLI_task由CLI_open间接调用)
  2. CLI_task。这个命令行接口任务提供了简化的"shell"接口,允许通过mmWave接口(MMwave_config)配置BSS。它解析输入CLI配置命令,如chrip配置文件和GUI配置。当传感器启动CLI命令被解析后,将执行与启动传感器和启动数据路径处理相关的的所有操作。当传感器停止CLI命令被解析后,将采取所有与停止传感器和停止数据路径处理相关的操作
  3. MmwDemo_mmWaveCtrlTask。这个任务用于提供为mmWave控制提供一个执行上下文,它在一个无限循环中调用MMWave_execute API
  4. mmwDemo_mssDPMTask。这个任务用于为DPM(数据路径管理器)执行提供上下文,它在一个无限循环中调用。没有DPM注册的DPC

DSS

  1. MmwDemo_initTask。该任务由main创建/调用,是一个一次性活动任务,其主要功能是初始化驱动程序(_init),DPM模块(DPM_init),数据路径相关驱动程序(EDMA、HWA),以及创建以下任务
  2. MmwDemo_DPC_ObjectDetection_dpmTask。这个任务用于为DPM(数据路径管理器)执行提供执行上下文,它在一个无限循环中调用DPM_execute API。在此上下文中,所有已注册的对象检测DPC(数据链)APIs(如配置、控制和执行)都将发生。在这个任务中,当DPC的execute API产生检测到对象和其他结果时,他们被报告给MSS,在MSS中它们被传输出UART端口,以便使用visualizer进行显示

Data Path

在这里插入图片描述
在这里插入图片描述
数据路径处理包括采集ADC样本作为输入,生成检测到对象(点云等信息)从UART端口发送到PC。算法处理采用DPM注册对象检测DPC实现,在DPC中处理的细节可以从以下doxygen文档中看到:ti/datapath/dpc/objectdetection/objdethwa/docs/html/index.html

Output information sent to host

Output Packet

带有检测输出数据包通过UART每帧发送出去。每个包由头MmwDemo_output_message_header_t和TLV项的数量组成,TLV项包含MmwDemo_output_message_type_e中列举的各种类型的数据信息。类型的数值可以在mmw_output.h中找到。每个TLV项由类型、长度(MmwDemo_output_message_tl_t)和有效负载信息组成。输出包的结构如下图所示,由于数据包的长度取决于检测到的对象的数量,因此它可以从一帧到另一帧变化。包的末端被填充,以便包的总长度是32的倍数

在这里插入图片描述

List of detected objects

类型:(MMWDEMO_OUTPUT_MSG_DETECTED_POINTS)
长度:(检测到物体的数量)x(DPIF_PointCloudCartesian_t的大小)
值:检测到对象的数组,每个被检测到对象的信息作为每一个DPIF_PointCloudCartesian_t结构。当检测到的对象的数量为0时,不发送此TLV项。在一个子帧/帧中可以检测到的最大对象数是DPC_OBJDET_MAX_NUM_OBJECTS
x,y,z轴相对于传感器的方向如图所示:
在这里插入图片描述

整个检测对象的TLV结构如下图所示:
在这里插入图片描述

Range profile

类型:(MMWDEMO_OUTPUT_MSG_RANGE_PROFILE)
长度:(Range FFT大小)x(uint16_t的大小)
值:第0多普勒剖面点阵列(静止物体)。点表示接收天线的log2大小的和,用Q9格式表示

Noise floor profile

类型:(MMWDEMO_OUTPUT_MSG_NOISE_PROFILE)
长度:(Range FFT大小)x(uint16_t的大小)
值:这是与距离剖面相同的格式,但剖面是在最大多普勒bin(最大速度物体)。一般来说,对于静止的物体,在最大速度下不会有物体或杂波,所以在这样的速度下的距离轮廓表示接收噪声的下限

Azimuth static heatmap

类型:(MMWDEMO_OUTPUT_MSG_AZIMUT_STATIC_HEAT_MAP)
长度:(Range FFT大小)x(虚拟天线的数量)(cmplx16ImRe_t_的大小)
值:DPU_AoAProcHWA_HW_Resources::azimuthStaticHeatMap的阵列。天线的数据是复数形式,其顺序如下:第一部分是虚部,第二部分是实部
在这里插入图片描述
在此基础上,通过运行在主机上的图形用户界面构建了静态方位热图

Range/Dropper heatmap

类型:(MMWDEMO_OUTPUT_MSG_RANGE_DOPPLER_HEAT_MAP)
长度:(Range FFT大小)x(Doppler FFT大小)(uint16_t的大小)
值:检测矩阵DPIF_DetMatrix::data。顺序是:
在这里插入图片描述

Stats information

类型:(MMWDEMO_OUTPUT_MSG_STATS)
长度:(MmwDemo_output_message_stats_t的大小)
值:根据MmwDemo_output_message_stats提供的计时信息。参见下面与统计数据相关的计时图
在这里插入图片描述
注意:

  • MmwDemo_output_message_stats_t:: interChirpProcessingMargin没有被计算(它总是设置为0),这是因为没有CPU参与1d处理(只包括HWA和EDMA),在没有CPU线性调频脉冲处理时它不可能知道多少的余裕应该被注意每个线性调频脉冲当处理开始(线性调频事件)的时候和HWA-EDMA计算结束的时候。在1D处理期间,CPU故意保持空闲状态,因为真正的应用程序可能会利用这段时间执行一些后续的处理算法
  • 虽然MmwDemo_output_message_stats_t::interFrameProcessingTime报告当前的子帧/帧,MmwDemo_output_message_stats_t:: interFrameProcessingMargin和MmwDemo_output_message_stats_t:: transmitOutputTime将前面的子帧(相同MmwDemo_output_message_header_t::subFrameNumber作为当前子帧)或先前的子帧
  • MmwDemo_output_message_stats_t::interFrameProcessingMargin不包含UART的传输时间(可以使用MmwDemo_output_message_stats_t::transmitOutputTime)。这样做的目的时为了让用户知道真正的帧间处理余裕,而不会受到像UART这样的缓慢传输的影响,例如,当输出调试信息(如热图时),这样的传输时间就会大大延迟。另外,在实际的产品部署中,可能会使用更快的接口(例如LVDS)来代替UART。用户可以使用统计数据计算包含传输开销的余裕(比如确定演示配置将允许的最大帧率),因为它们也包含UART传输时间

Side information of detected objects

类型:(MMWDEMO_OUTPUT_MSG_DETECTED_POINTS_SIDE_INFO)
长度:(检测物体的数量)x(DPIF_PointCloudSideInfo_t的大小)
值:检测到的对象的边数组信息。每个被检测对象的边信息按照结构(DPIF_PointCloudSideInfo_t)。当检测到的对象数量为0时,不发送此TLV项

Temperature Stats

类型:MMWDEMO_OUTPUT_MSG_TEMPERATURE_STATS
长度:MmwDemo_temperatureStats_t的大小
值:从雷达前端获得的详细温度报告的结构。MmwDemo_temperatureStats_t::tempReportValid被设置为rlRfGetTemperatureReport的返回值。如果MmwDemo_temperatureStats_t::tempReportValid为0,则MmwDemo_temperatureStats_t::temperatureReport中的值是有效的,否则应该忽略它们。此TLV与Stats信息中描述的Stats TLV一起发送

Range Bias and Rx Channel Gain/Phase Measurement and objects

由于电路板上天线布局的缺陷,在SOC中存在射频延迟等,在距离估计、接收通道增益和相位缺陷中需要对传感器进行校正以补偿偏差。下图说明了校准的过程:
在这里插入图片描述
校准过程包含下面的几个部分:

  • 在基准线X米远处(不建议X小于50厘米)设置一个像角反射镜的强目标
  • 在配置概要文件中…/profiles/profile_calibration.cfg设置以下命令,来反映X位置如下:在这里插入图片描述
    其中D(单位为米)是搜索峰值的X附近的窗口距离,搜索窗口的目的是让测试环境不受到过度的限制,因为它不可能清除所有可能比用于校准的反射器更强的反射器。推荐的窗口大小至少等于几个range bins的距离。校准配置文件(profile_calibration.cfg)的一个range bin大约是5cm。第一个参数"1"用于启动度量。必须使用所述的配置文件(.cfg),否则校准可能无法按预期工作(该配置文件确保所有发射和接收天线都在校准所需的其他事物中工作)
  • 使用配置文件启动传感器
  • 在配置文件中启用了测量,因为DPC进行配置并生成测量结果(DPU_AoAProc_compRxChannelBiasCfg_t)结构DPC_ObjectDetection_ExecuteResult_t:: compRxChanBiasMeasurement),测量结果将被写入到CLI端口(MmwDemo_measurementResultOutput) 下面的格式:在这里插入图片描述
    有关DPC如何执行度量的详细信息,请参阅DPC文档
  • 现在可以将CLI打印的命令复制并粘贴到任何配置文件中,以便进行校正。此配置将被传递给DPC,用于在角度计算期间应用补偿,细节可以在DPC文档中看到。如果不需要补偿,则应该给出以下的命令:在这里插入图片描述
    以上设置的范围偏差为0,相位系数为统一,因此没有校正。注意,在任何配置文件中都必须给出这两个命令。当所需的是纠正命令是,度量command将被禁用

Streaming data over LVDS

LVDS流特性允许通过LVDS接口流化HW数据(ADC/CP/CQ数据的组合)和/或用户特定的SW数据。流处理主要由CBUFF和EDMA外围设备完成,CPU干预最少。流是通过MmwDemo_LvdsStreamCfg_t CLI命令进行配置的,该命令允许控制HSI头、HW和SW数据的启用/禁用以及HW数据的数据格式选择。HW的数据格式选择是:

  • MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_DISABLED
  • MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_ADC
  • MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_CP_ADC_CQ

为了查看与上述数据格式配置对应的高级数据格式细节,请参考ti/drivers/cbuff/docs/cbuff_transferring.pptx中相应的幻灯片
当HW数据LVDS流启用时,在每个chrip事件上,每一个chrip对ADC/CP/CQ数据进行流处理。当SW数据流被启用时,它将计算该帧检测到对象列表后的帧间期间流。SW数据流的每一帧/子帧在时间上由以下部分完成:

  1. HSI头(HSIHeader_t):详细信息请参考HSI模块
  2. 用户数据头:MmwDemo_LVDSUserDataHeader
  3. 用户数据有效载荷:
    1. Point-cloud信息作为列表:DPIF_PointCloudCartesian_t x检测到的对象数量
    2. Point-cloud side信息作为列表:DPIF_PointCloudSideInfo_t x检测到的对象数量

SW数据流的格式如下:

在这里插入图片描述
注意:

  1. 只允许sigle-chirp格式,不支持multi-chitp
  2. 当帧/子帧中检测到的的对象数为0时,没有用户数据头以外的传输
  3. 对于HW数据,inter-chrip持续时间应该满足流出数据的数量,例如,HW数据格式为ADC,HSI包头启用,则每个chirp产生的总数据量为:(numAdcSamples * numRxChannels * 4(size of complex sample) + 52[sizeof(HDSDataCardHeader_t) + sizeof(HSISDKHeader_t)])四舍五入到256[=sizeof(HSIHeader_t)]字节的倍数,chrip的时间为(us为单位) = 空闲时间 + 在配置文件中的斜坡结束时间。对于n个通道为LVDS并且每个通道最大值为BMbps,每个chrip可以发送的最大字节数为:Tc * n * B / 8,它应该大于每个chrip生成的总数量,即Tc * n * B / 8 》= round-up(numAdcSamples * numRxChannels * 4 + 52,256)。如果n=2,B=600Mbps,空闲时间=7us,ramp结束时间=44us,numAdcSamples=512,numRxChannels=4,则违反了7650>=8448,因此这个配置将不能工作。如果在上面的例子中空闲时间增加了一倍,那我们有8700》8448,所以这种配置可以工作
  4. 对于SW数据,每个子帧/帧传输的字节数为:52[sizeof(HSIDataCardHeader_t)+sizeof(HSISDKHeader_t)] + sizeof(MmwDemo_LVDSUserDataHeader_t)[=8] + 检测到的对象数(Nd) * {sizeof(DPIF_PointCloudCartesian_t)[=16] + sizeof(DPIF_PointCloudSideInfo_t)[=4]}四舍五入到256个[=sizeof(HSIHeader_t)]字节的倍数。或者X=round-up(60+Nd*20,256)。因此传输数据的时间为X * 8 / (n * B)us。可以检测到的最大对象数量(Ndmax)在DPC中定义(DPC_OBJDET_MAX_NUM_OBJECTS)。因此如果Ndmax=500,那么传输SW数据的时间为68us。因为我们用更慢的UART传输分析这个传输,而且因为UART要传输和LVDS相同的的信息,LVDS传输时间不会添加任何负担处理预算之外的开销重新配置和激活CBUFF会话(这开销可能会超过时间传输)
  5. 在HW或SW包中传输的数据总量必须大于CBUFF所要求的最小值,即64字节或32个单元(这是CBUFF_MIN_TRANSFER_SIZE_CBUFF_UNITS在CBUFF驱动程序中实现定义),如果违反了这个阈值条件,CBUFF驱动程序在配置过程中返回一个错误,演示结果将生成一个致命的异常。当启用HSI报头时,确保总的传输字节至少是256字节,这满足最小值。如果HSI头是禁用的,对于HW会话,这意味着numAdcSamples * numRxChannels * 4 >= 64。尽管mmWavelink允许最小模数为2的ADC样本,但是演示程序支持numAdcSamples>=64。因此HSI头部并不需要仅在HW情况下启用。但如果SW会话是启用的,没有HSI头,每个包中的字节将是8+Nd*20,因此对于Nd<3的帧/子帧,demo将产生异常。因此,如果启用了SW,则必须启用HSI头,这将在CLI命令验证中检查。

Implementation Notes

  1. LVDS实现主要出现在mmw_lvds_stream.h和mmw_lvds_stream.c中,并在mss_main.c中调用。此外,HSI时钟初始化在传感器第一次调用MmwDemo_mssSetHsiClk完成
  2. CBUFF/LVDS的EDMA通道资源在全局的资源文件中(mmw.res.h,参考硬件资源分配)以及其他EDMA的资源分配。在CBUFF驱动程序中,用户数据头和两个用户有效负载被配置为三个用户缓冲区。因此,针对EDMA的SW分配提供了三组EDMA资源,如MmwDemo_LVDSStream_LVDSInit的SW部分(swSessionEDMAChannelTable[.])所示。HW EDMA的资源的最大值被数据格式MMW_DEMO_LVDS_STREAM_CFG_DATAFMT_CP_ADC_CQ所需要,可以看相应的幻灯片在 ti\drivers\cbuff\docs\CBUFF_Transfers.pptx是12个channel(+shadows)包括第一个特殊的CBUFF EDMA时间通道由CUBFF IP生成EDMA,因此MmwDemo_LVDSStream_EDMAInit的HW部分(hwwSessionEDMAChannelTable[.])有11个表条目。
  3. 尽管CBUFF驱动程序被配置为两个会话(hw和sw),但在任何一个时候只有一个会话是活动的,因此,根据LVDS CLI配置和是否使用advanced frame,有必要激活/禁用HW和SW会话的逻辑
  4. CBUFF会话(HW/SW)配置创建和删除取决于在第一次配置之后是否需要重新配置
    1. 对于HW会话,在子帧切换时进行重新配置以重新配置下一个子帧,但当没有advanced frame(子帧的数目=1)时,HW配置不需要更改,因此HW会话不需要重新创建
    2. 对于SW会话,即使用户缓冲区的起始地址和头文件大小任然保持不变,检测到的对象的数量决定了一些用户缓冲区的大小从一个子帧/帧到另一个子帧/帧的变换。因此SW会话需要重新创建每一个子帧/帧
  5. 用户可以修改应用软件,在雷达立方体数据(range DPU的输出)等SW数据中传输与点云不同的信息,然后,CBUFF还有一个最大链接列表条目大小限制,即0x3FFF CBUFF单位或32766字节。这意味着它是每个用户缓冲区条目的限制(最多有3个条目-第1个用于用户数据头,第二个用于point-cloud信息,第三个用于point-cloud side信息)。在创建会话期间,如果超过了这个限制,CBUFF将返回一个错误(demo将生成一个异常)。单个物理缓冲地址的大小为50000字节可能分隔两个用户缓冲区通过提供一个用户缓冲区(地址、大小)=(起始地址,25000)和第二个用户缓冲区(地址,大小)=(起始地址+25000,25000),除了这两个(或三个如果用户数据头也取代)限制,用户将需要创建并激活(并等待完成)多次SW会话来完成传输

下图显示了LVDS流的时间关系图(此图没有用放缩,因为时间持续时间将根据配置变换)
在这里插入图片描述

How to bypass CLI

重新执行文件mmw_cc.c如下:

  1. MmwDemo_CLIInit应该只创建一个带有输入taskPriority的任务。假设任务名为"MmwDemo_sensorConfig_task"
  2. 其他功能都不需要
  3. 执行MmwDemo_sensorConfig_task如下:
    1. Fill gMmwMssMCB.cfg.openCfg
    2. Fill gMmwMssMCB.cfg.ctrlCfg
    3. 使用MMWave_addProfile和MMWave_addChirp函数添加orofiles和chirp
    4. 为存储CLI配置的偏移量中的每个偏移量调用MmwDemo_CfgUpdate(MMWDEMO_xxx_OFFSET在mmw_mss.h中)
    5. Fill gMmwMssMCB.objDetCommonCfg.preStartCommonCfg
    6. 调用MmwDemo_openSensor
    7. 调用MmwDemo_configSensor
    8. 调用MmwDemo_startSensor(可以使用辅助函数MmwDemo_isAllCfgInPendingState来知道是否提供了所有的动态配置)

Hardware Resource Allocation

对象检测DPC需要配置DPUs硬件资源(HWA、EDMA)。尽管硬件资源目前只需要为这个DPC分配,而且系统中只有DPC需要分配,但是资源分区显示为demo的所有者。这是为了说明跨多个dpc和/或演示自己的处理(即后dpc处理)进行资源分配的一般情况。这个分区可以在mmw_res.h文件中看到。此文件作为编译器命令行定义传递
在这里插入图片描述
在mmw_mss.mak和mmw_dss.mak。当构建DPC源作为构建演示应用程序的一部分时,在需要的地方对象检测DPC源中被引用:
在这里插入图片描述

Design Notes

由于DPM本地队列大小的限制,对于某些DPM函数,如DPM_start、DPM_stop以及通过DPM_ioctl进行一些DPC控制,信号量用于在调用任务和函数MmwDemo_DPC_ObjectDetection_reportFxn之间进行同步。这样它就不会因为DPM本地队列耗尽而导致DPM崩溃。下图演示了阻塞DPM_ioctl()函数调用的调用流示例。为了进行比较,还显示了非阻塞的DPM_ioctl。
在这里插入图片描述
对于相同的DPM_Report,在MSS和DSS上都有DPM报告功能。然而,两个核心之间的序列不能保证

Memory Usage

Memory usage summary

下表显示了跨演示应用程序和其他SDK组件在设备上可用的各种内存使用情况。这个表是使用演示的映射文件生成的,并对它应用了一些映射规则来生成一个压缩摘要。这里显示的数值表示字节
MSS: 有关映射规则,请参考demo_mss_mapping.txt。请参考xwr18xx_mmw_demo_mss_mem_analysis_detail.txt了解MSS上驱动程序和控制/alg组件之间的内存使用情况的详细分析。并参阅demo_mss_mapping_detail.txt了解详细的映射规则
在这里插入图片描述
DSS: 有关映射规则,请参考demo_dss_mapping.txt。请参考xwr18xx_mmw_demo_dss_mem_analysis_detail.txt了解MSS上驱动程序和控制/alg组件之间的内存使用情况的详细分析。并参阅demo_dss_mapping_detail.txt了解详细的映射规则

在这里插入图片描述

Note on Error Codes

当demo遇到错误情况时,错误代码将被生成并打印出来。错误代码被定义为负整数。它包括以下几类:

  • Drivers
  • Control modules
  • Data Processing Chain
  • Data Processing Unit
  • Demo

错误代码定义为(Module error code base - Module specific error code)
以上模块的基本错误代码可以在mmwave_error.h中找到
DPC和DPU的基本错误代码可以在dp_error.h中找到
模块特定的错误代码是在模块的头文件中指定的。例如:

  • UART驱动错误代码被定义在uart.h
  • DPC错误代码在用dpc的demo中定义(ti/datapaht/dpc/objectdetection/objecthwa)

mmWave module Error Code

mmWave模块的错误编码方式如下:
在这里插入图片描述

  • mmwave错误被在mmwave.h中定义
  • 子系统错误由mmwavelink和邮箱驱动等子系统返回
  • 错误等级是指警告等级和错误等级
  • mmWave公开了一个API-MMWave_decodeError(),可以在demo中用于解码错误代码

Example

  • 下面是一个如何解析错误代码"-40111"
    1. 错误代码是来自基为"-40000",表示为DPC错误
    2. 通过参考dp_error.h,“-40100”来自于基于HWA的对象检测DPC
    3. 然后再objectdetection.h找到错误代码(-11),即DPC_OBJECTDETECTION_ENOMEM__L3_RAM_RADAR_CUBE
  • 另一个例子是mmWave控制模块:-“mmWave配置失败[错误代码:-3109子系统:71]”
    1. 以上消息表明错误来自模块(-3100->mmwave)错误为-9(MMWAVE_ECHIRPCFG)
    2. 在mmwavelink,h发现的子系统误差为71(RL_RET_CODE_CHIRP_TX_ENA_1INVAL_IN)

参考文献:

  1. 《mmwave_sdk_module_documentation.html》
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xiaojie雷达说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值