S3C6410 纯粹的裸机SD卡启动

转载地址 http://blog.csdn.net/cp1300/article/details/17252217

原博主用的是2G  SD卡 算出的偏移地址为 0X2400 Byte  (注意是从结尾向前的偏移量)

 对于使用 SDHC卡的朋友可以参考《S3C6410_Internal_ROM_Booting》这个手册 里面讲了S3C6410从IROM启动的过程

用的 SDHC卡的 算出的偏移地址为 0X82400 Byte  (注意是从结尾向前的偏移量)

S3C6410_Internal_ROM_Booting》中的两种卡 BL0 存放的位置:

原文:


这几天晚上一直折腾S3C6410的裸机SD卡启动,不大想使用UBOOT,我是搞硬件的,对底层非常感兴趣,不喜欢已经写好的,因此自己一直在尝试,其实很早之前就试过SD卡启动,也就是ARM11上电后会把SD卡倒数第9KB开始的8KB(倒数0x2400B偏移量)复制到内部SRAM中执行,这个比较简单,但是代码量只有8K,不能像STM32一样玩,因此查阅相关资料,得知启动方式为L0加载L1,L1加载L2,简单来说,就是上电启动后,固化在S3C6410内部的L0代码启动,将NAND,SD卡等外部存储器映射或者复制到内部SRAM,这个从SD卡或者flash复制过去的代码称之为L1,也就是用户的启动代码,在电脑上相当于硬盘主分区的启动代码和BIOS,用来初始化外时钟以及外设,并启动系统,,这部分代码只有8KB因此完成的工作有限,因此可以使用这段代码完成初始化并复制操作系统或者更大的代码到内存,这部分代码就是L2了,只有L1将内存初始化后才能使用内存,再此之前内存只有8KB,就是内部SRAM,从SD卡启动的时候映射到0x0c000000,从NAND可以是0,也可以是0x0c000000.

目前只实现了L1,无需uboot,只需要烧写到SD卡的指定位置即可,需要将开发板选择为SD卡启动.


启动代码,完成了关闭看门狗,初始化时钟,SDRAM内存,堆栈,VIC,中断等操作(启动代码来自互联网)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.     INCLUDE S3C6410.inc  
  2.     PRESERVE8  
  3.     AREA Init, CODE, READONLY  
  4. STACK_BASEADDRESS EQU  0x0c000400;0x52000000  
  5.   
  6. SVCStack    EQU (STACK_BASEADDRESS) ;管理模式  
  7. UndefStack  EQU (STACK_BASEADDRESS - 0x300) ;指令终止模式  
  8. AbortStack  EQU (STACK_BASEADDRESS - 0x300) ;数据访问终止模式  
  9. IRQStack    EQU (STACK_BASEADDRESS - 0x200) ;中断模式  
  10. FIQStack    EQU (STACK_BASEADDRESS - 0x100) ;快速中断模式   
  11.       
  12. ;---------------------------  
  13. ; CPSR Mode Bit Definition  
  14. ;---------------------------  
  15. Mode_USR    EQU    (0x10)  
  16. Mode_FIQ    EQU    (0x11)  
  17. Mode_IRQ    EQU    (0x12)  
  18. Mode_SVC    EQU    (0x13)  
  19. Mode_ABT    EQU    (0x17)  
  20. Mode_UND    EQU    (0x1B)  
  21. Mode_SYS    EQU    (0x1F)  
  22. Mode_MASK    EQU    (0x1F)  
  23. NOINT        EQU    (0xC0)  
  24. I_Bit        EQU    (0x80)  
  25. F_Bit        EQU    (0x40)    
  26.       
  27.   
  28.       
  29.       
  30. ;异常处理函数    
  31. ;---------------------------------------------------------------------------------------------------      
  32.     IMPORT main  
  33.     EXPORT  ResetHandler  
  34.       
  35. ResetHandler  
  36.     ldr        r0, =0x70000013        ; Base Addres : 0x70000000, Size : 256 MB (0x13)  
  37.     mcr        p15,0,r0,c15,c2,4      ;告诉CPU外设寄存器的基地址和地址空间 重要  
  38. ;设置为SVC模式  
  39.     MRS     R0,CPSR  
  40.     BIC     R0,R0,#0x1F  
  41.     ORR     R0,R0,#0xD3  
  42.     MSR     CPSR_cxsf,R0  
  43.   
  44.   
  45.   
  46. ;未知模式堆栈  
  47.         mrs r0,cpsr  
  48.         bic r0,r0,#Mode_MASK  
  49.         orr r1,r0,#Mode_UND|NOINT  
  50.         msr cpsr_cxsf,r1        ;UndefMode  
  51.         ldr sp,=UndefStack    
  52.   
  53.         ;异常模式堆栈  
  54.         orr r1,r0,#Mode_ABT|NOINT  
  55.         msr cpsr_cxsf,r1        ;AbortMode  
  56.         ldr sp,=AbortStack    
  57.   
  58.         ;中断模式堆栈  
  59.         orr r1,r0,#Mode_IRQ|NOINT  
  60.         msr cpsr_cxsf,r1        ;IRQMode  
  61.         ldr sp,=IRQStack      
  62.   
  63.         ;管理模式堆栈  
  64.         bic r0,r0,#Mode_MASK|NOINT  
  65.         orr r1,r0,#Mode_SVC  
  66.         msr cpsr_cxsf,r1        ;SVCMode  
  67.         ldr sp,=SVCStack  
  68.           
  69. ;禁止看门狗  
  70.     LDR     R0,=rWTCON  
  71.     LDR     R1,=0x0  
  72.     STR     R1,[R0]  
  73. ;禁止cache和mmu      
  74.       
  75.     LDR     R0,=0x0  
  76.     MRC     p15,0,R0,c1,c0,0  
  77.     LDR     R1,=0xFFFF  
  78.     BIC     R0,R0,R1  
  79.     MCR     p15,0,R0,c1,c0,0  
  80.           
  81.       
  82. ;禁止所有中断  
  83.   
  84.     LDR     R0,=rVIC0INTENCLEAR   
  85.     LDR     R1,=0xFFFFFFFF  
  86.     STR     R1,[R0]  
  87.       
  88.     LDR     R0,=rVIC1INTENCLEAR   
  89.     LDR     R1,=0xFFFFFFFF  
  90.     STR     R1,[R0]  
  91. ;---------------------------------------------------------------------------------------------------      
  92.   
  93. ;设置时钟源  
  94.     LDR     R0,=rOTHERS  
  95.     LDR     R1,[R0]  
  96.     ORR     R1,R1,#(1<<6)  
  97.       
  98.     LDR     R0,=rCLK_SRC  
  99.     LDR     R1,=(1<<13)|7  
  100.     STR     R1,[R0]  
  101.   
  102.     LDR     R0,=rCLK_SRC2  
  103.     LDR     R1,=0x0  
  104.     STR     R1,[R0]  
  105.       
  106. ;设置时钟分频  
  107.     LDR     R0,=rCLK_DIV0  
  108.     LDR     R1,=0x01043310  
  109.     STR     R1,[R0]  
  110.       
  111.     LDR     R0,=rCLK_DIV1  
  112.     LDR     R1,=0x0  
  113.     STR     R1,[R0]  
  114.   
  115.     LDR     R0,=rCLK_DIV2  
  116.     LDR     R1,=3<<16  
  117.     STR     R1,[R0]  
  118.                   
  119.       
  120. ;使能时钟  
  121.     LDR     R0,=rHCLK_GATE  
  122.     LDR     R1,=0xFFFFFFFF  
  123.     STR     R1,[R0]  
  124.       
  125.     LDR     R0,=rPCLK_GATE  
  126.     STR     R1,[R0]  
  127.       
  128.     LDR     R0,=rSCLK_GATE  
  129.     STR     R1,[R0]  
  130.       
  131. ;设置系统时钟   
  132. ;设置APLL 532MHz  
  133.     LDR     R0,=rAPLL_LOCK  
  134.     LDR     R1,=0xFFFF  
  135.     STR     R1,[R0]  
  136.       
  137.     LDR     R0,=rAPLL_CON  
  138.     LDR     R1,=(1<<31)|(266<<16)|(3<<8)|(1)    
  139.     STR     R1,[R0]  
  140.   
  141. ;设置MPLL 532MHz  
  142.     LDR     R0,=rMPLL_LOCK  
  143.     LDR     R1,=0xFFFF  
  144.     STR     R1,[R0]  
  145.       
  146.     LDR     R0,=rMPLL_CON  
  147.     LDR     R1,=(1<<31)|(266<<16)|(3<<8)|(1)    
  148.     STR     R1,[R0]  
  149.       
  150. ;设置EPLL 96MHz  
  151.     LDR     R0,=rEPLL_LOCK  
  152.     LDR     R1,=0xFFFF  
  153.     STR     R1,[R0]  
  154.       
  155.     LDR     R0,=rEPLL_CON0  
  156.     LDR     R1,=(1<<31)|(32<<16)|(1<<8)|(2)  
  157.     STR     R1,[R0]  
  158.       
  159.     LDR     R0,=rEPLL_CON1  
  160.     LDR     R1,=0x0  
  161.     STR     R1,[R0]   
  162. ;=================  
  163. ;选择同步工作模式  
  164. ;=================  
  165.     ldr     r4, =rOTHERS  
  166.     ldr     r5, [r4]  
  167.     bic     r5, r5, #0xC0  
  168.     orr     r5, r5, #0x40           ; SyncReq = Async, SyncMUX = Sync  
  169.     str     r5, [r4]  
  170.       
  171. _wait_for_async                     ;确认工作到同步模式  
  172.     ldr     r5, [r4]                ; Read OTHERS  
  173.     and     r5, r5, #0xF00          ; Wait SYNCMODEACK = 0x0  
  174.     cmp     r5, #0x0  
  175.     bne     _wait_for_async  
  176.   
  177.     ldr     r4, =rOTHERS  
  178.     ldr     r5, [r4]  
  179.     bic     r5, r5, #0x40           ;SyncMUX = Async  
  180.     str     r5, [r4]  
  181.   
  182.     nop  
  183.     nop  
  184.     nop  
  185.     nop  
  186.     nop       
  187. ;---------------------------------------------------------------------------------------------------      
  188. ;设置DRAM  
  189.     LDR     R0,=0x7E00F120    
  190.     LDR     R1,=0xD  
  191.     STR     R1,[R0]  
  192.           
  193.     LDR     R0,=rP1MEMCCMD  
  194.     LDR     R1,=0x4  
  195.     STR     R1,[R0]  
  196.       
  197.     LDR     R0,=rP1REFRESH        
  198.     LDR     R1,=0x40D  
  199.     STR     R1,[R0]  
  200.       
  201.   
  202.     LDR     R0,=rP1CASLAT         
  203.     LDR     R1,=0x6  
  204.     STR     R1,[R0]   
  205.       
  206.     LDR     R0,=rP1T_DQSS  
  207.     LDR     R1,=0x1  
  208.     STR     R1,[R0]  
  209.       
  210.     LDR     R0,=rP1T_MRD  
  211.     LDR     R1,=0x2  
  212.     STR     R1,[R0]  
  213.     LDR     R0,=rP1T_RAS  
  214.     LDR     R1,=0x6  
  215.     STR     R1,[R0]  
  216.   
  217.     LDR     R0,=rP1T_RC  
  218.     LDR     R1,=0xA  
  219.     STR     R1,[R0]  
  220.   
  221.     LDR     R0,=rP1T_RCD  
  222.     LDR     R1,=0xB  
  223.     STR     R1,[R0]  
  224.       
  225.     LDR     R0,=rP1T_RFC  
  226.     LDR     R1,=0x10B  
  227.     STR     R1,[R0]  
  228.   
  229.     LDR     R0,=rP1T_RP  
  230.     LDR     R1,=0xB  
  231.     STR     R1,[R0]  
  232.       
  233.     LDR     R0,=rP1T_RRD  
  234.     LDR     R1,=0x2  
  235.     STR     R1,[R0]  
  236.       
  237.     LDR     R0,=rP1T_WR  
  238.     LDR     R1,=0x2  
  239.     STR     R1,[R0]  
  240.       
  241.     LDR     R0,=rP1T_WTR  
  242.     LDR     R1,=0x2  
  243.     STR     R1,[R0]  
  244.       
  245.     LDR     R0,=rP1T_XP  
  246.     LDR     R1,=0x2  
  247.     STR     R1,[R0]  
  248.       
  249.     LDR     R0,=rP1T_XSR  
  250.     LDR     R1,=0x10  
  251.     STR     R1,[R0]  
  252.       
  253.     LDR     R0,=rP1T_ESR  
  254.     LDR     R1,=0x10  
  255.     STR     R1,[R0]  
  256.       
  257.     LDR     R0,=rP1MEMCFG  
  258.     LDR     R1,=0x1001A  
  259.     STR     R1,[R0]  
  260.       
  261.     LDR     R0,=rP1MEMCFG2  
  262.     LDR     R1,=0xB45  
  263.     STR     R1,[R0]   
  264.       
  265.     LDR     R0,=rP1_chip_0_cfg  
  266.     LDR     R1,=0x150F0  
  267.     STR     R1,[R0]  
  268.       
  269.     LDR     R0,=rP1_user_cfg  
  270.     LDR     R1,=0x0  
  271.     STR     R1,[R0]  
  272.       
  273.     LDR     R0,=rP1_DIRECTCMD  
  274.     LDR     R1,=0xC0000  
  275.     STR     R1,[R0]  
  276.       
  277.     LDR     R0,=rP1_DIRECTCMD  
  278.     LDR     R1,=0x00000  
  279.     STR     R1,[R0]  
  280.       
  281.     LDR     R0,=rP1_DIRECTCMD  
  282.     LDR     R1,=0x40000  
  283.     STR     R1,[R0]  
  284.     STR     R1,[R0]  
  285.       
  286.     LDR     R0,=rP1_DIRECTCMD  
  287.     LDR     R1,=0xA0000  
  288.     STR     R1,[R0]  
  289.       
  290.     LDR     R0,=rP1_DIRECTCMD  
  291.     LDR     R1,=0x80032  
  292.     STR     R1,[R0]  
  293.       
  294.     LDR     R0,=rP1MEMCCMD  
  295.     LDR     R1,=0x0  
  296.     STR     R1,[R0]  
  297.   
  298.     LDR     R0,=rP1MEMSTAT    
  299. DRAM_WAIT  
  300.     LDR     R1,[R0]  
  301.     AND     R1,R1,#0x3  
  302.     CMP     R1,#0x1  
  303.     BNE     DRAM_WAIT  
  304. ;---------------------------------------------------------------------------------------------------      
  305.   
  306.   
  307.       
  308.   
  309. ;设置堆栈  
  310. ;STACK_TOP  EQU 0x52000000;0x0c000400     
  311. ;   LDR     SP,=STACK_TOP  
  312.   
  313. ;---------------------------------------------------------------------------------------------------  
  314. ;使能VIC  
  315.     mrc     p15,0,r0,c1,c0,0  
  316.     orr     r0,r0,#(1<<24)  
  317.     mcr     p15,0,r0,c1,c0,0  
  318. ;---------------------------------------------------------------------------------------------------  
  319. ;使能VFP  
  320.     MRC        p15, 0, r0, c1, c0, 2   
  321.     ORR        r0, r0, #0x00F00000   
  322.     MCR        p15, 0, r0, c1, c0, 2   
  323.       
  324.     MOV        r1, #0   
  325.     MCR        p15, 0, r1, c7, c5, 4   
  326.     MOV        r0,#0x40000000   
  327.     FMXR       FPEXC, r0       ; FPEXC = r0   
  328.     nop   
  329.     nop   
  330. ;---------------------------------------------------------------------------------------------------  
  331.     LDR     R0,=rGPMCON  
  332.     LDR     R1,=0x11111  
  333.     STR     R1,[R0]  
  334.       
  335.     LDR     R0,=rGPMPUD  
  336.     LDR     R1,=0x0  
  337.     STR     R1,[R0]  
  338.       
  339.     LDR     R0,=rGPMDAT  
  340.     LDR     R1,=0  
  341.     STR     R1,[R0]  
  342.   
  343.     B       main  
  344.   
  345.           
  346.   
  347.           
  348.       
  349.     END  

//主要的函数

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "system.h"  
  2. #include "uart.h"  
  3. #include "other.h"  
  4. #include "SDCARD.h"  
  5.   
  6.   
  7. //简单的延时  
  8. void Delay_Ms(u32 n)  
  9. {  
  10.     u32 i;  
  11.       
  12.     while(n --)  
  13.     {  
  14.         for(i = 0;i < 0xfff;i ++)  
  15.         {  
  16.             nop;  
  17.         }  
  18.                
  19.     }  
  20.       
  21. }  
  22.   
  23.   
  24.   
  25. //跳转到指定位置执行  
  26. __asm jump()  
  27. {  
  28.     LDR PC,=0x52000000;  
  29. }  
  30.   
  31.   
  32.   
  33. //按键检测  
  34. bool Key_Test(void)  
  35. {  
  36.     static u8 i = 0;  
  37.       
  38.     if((rGPNDAT & 0x3f) != 0x3f )  
  39.     {  
  40.         i ++;  
  41.         if(i > 10)  
  42.         {  
  43.             i = 0;  
  44.               
  45.             return TRUE;  
  46.         }  
  47.     }  
  48.     return FALSE;  
  49. }  
  50.   
  51.   
  52. //主函数  
  53. int main(void)  
  54. {     
  55.     u16 n = 0;  
  56.     u32 cnt1 = 0, cnt2 = 0;  
  57.   
  58.     LED_Init();                 //初始化LED  
  59.     UART0_Init(ENABLE,115200);  //初始化串口  
  60.     UARTx_SetRxBuff(UART_CH0, (u8 *)0x52000000, 1024*1024*10);  //设置串口接收缓冲区  
  61.     rGPNCON = 0;                //初始化按键  
  62.     UART0_SendString("SD BOOT 启动成功!\r\n");  
  63.       
  64.     Delay_Ms(100);  
  65.       
  66.     //按键没有按下从SD卡加载程序  
  67.     if((rGPNDAT & 0x3f) == 0x3f)  
  68.     {  
  69.         Delay_Ms(10);  
  70.         if((rGPNDAT & 0x3f) == 0x3f )  
  71.         {  
  72.             if(SD_Init() == SD_OK)  
  73.             {  
  74.                 UART0_SendString("SD卡初始化成功!\r\n");  
  75.                 if(SD_ReadMultiBlocks(1621032, (u32 *)0x52000000, 1000) == SD_OK)  
  76.                 {  
  77.                     UART0_SendString("从SD卡读取程序成功,开始从0x52000000执行!\r\n");  
  78.                     jump();     //跳转  
  79.                 }  
  80.                 else  
  81.                 {  
  82.                     UART0_SendString("从SD卡读取程序失败!\r\n");  
  83.                     LED0_FLASH();  
  84.                 }  
  85.             }  
  86.             else  
  87.             {  
  88.                 UART0_SendString("SD卡初始化失败!\r\n");  
  89.             }  
  90.         }  
  91.     }  
  92.       
  93.       
  94.     while((rGPNDAT & 0x3f) != 0x3f);    //等待按键抬起  
  95.     Delay_Ms(100);  
  96.     //从串口加载程序  
  97.     UART0_SendString("请从串口发送代码!\r\n");  
  98.     while(1)  
  99.     {  
  100.         n ++;  
  101.         if(n == 300)  
  102.         {  
  103.             LED1_FLASH();  
  104.             n = 0;  
  105.             cnt1 = cnt2;  
  106.             cnt2 = UARTx_GetRxCnt(UART_CH0);  
  107.             if(cnt1!=cnt2)  
  108.             {  
  109.                 LED2_FLASH();  
  110.             }  
  111.             else if(cnt2 == 0)  
  112.             {  
  113.                   
  114.                 //UART0_SendString("请从串口发送代码!\r\n");  
  115.                 LED3_FLASH();  
  116.             }  
  117.         }  
  118.           
  119.           
  120.         if(Key_Test() == TRUE)  
  121.         {  
  122.             //测试检查内存  
  123.             *((vu32 *)0x59000000) = 0xa55aaa55;  
  124.             *((vu32 *)0x59000000)+=1;  
  125.             if(*((vu32 *)0x59000000) == (0xa55aaa55+1))  
  126.             {  
  127.                 UART0_SendString("内存0x59000000检查正确!\r\n");  
  128.             }  
  129.             else  
  130.             {  
  131.                 UART0_SendString("内存0x59000000检查错误!\r\n");  
  132.             }  
  133.             //测试检查内存  
  134.             *((vu32 *)0x54000000) = 0xaa5aaa55;  
  135.             *((vu32 *)0x54000000)-=1;  
  136.             if(*((vu32 *)0x54000000) == (0xaa5aaa55-1))  
  137.             {  
  138.                 UART0_SendString("内存0x54000000检查正确!\r\n");  
  139.             }  
  140.             else  
  141.             {  
  142.                 UART0_SendString("内存0x54000000检查错误!\r\n");  
  143.             }  
  144.             UART0_SendString("发送完成,开始从0x52000000执行!\r\n");  
  145.             jump();     //跳转  
  146.         }  
  147.         Delay_Ms(1);      
  148.     }  
  149. }  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. if(SD_ReadMultiBlocks(1621032, (u32 *)0x52000000, 1000)  
当没有按键按下的时候,或从SD卡指定位置加载一个比较的程序执行,可以是操作系统,或自己的裸机程序.

1621032:程序在SD卡中的位置,注意是物理扇区,不是逻辑扇区,物理扇区是你写的裸机代码能读的扇区地址,比如1,2,等,逻辑扇区是文件系统提供的扇区,两个位置不一样,要注意了.
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 0x52000000 程序启动的位置,在编译的时候就要指定好,一般在SDRAM中.  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 1000:需要加载的扇区数量,每个扇区大小为512B,因此我的程序加载的是512KB.  
 

 



1.使用串口下载程序

准备好后从串口下载程序,按住随便一个按键,RESET除外,即可使用串口下载程序,波特率115200,我使用的是OK6410开发板,因此按键检测为if((rGPNDAT & 0x3f) != 0x3f );


启动后使用串口把bin发送过去



发送完成后按任意按键(reset除外)即可开始执行


可以看到程序已经开始执行了,刚开始的时候我用串口下载程序,一段时间后CPU就会死掉,还得我折腾一下午,最后发现是CPU主频过高,初始化为633MHZ了,结果不稳定,现在是533MHZ比较稳定了.


2.我已经将要启动的大程序放到SD卡指定位置了,直接复位,不要按下任何按键即可加载,后面将会做上界面,选择启动哪个程序,就行安卓手机SD卡刷机一样,可以选启动程序.



3.启动程序如何写入到SD卡

写入还是比较简单的,看下面的图片

先使用十六进制编辑器打开磁盘,一定要是物理磁盘


指定偏移到倒数第0x2400B,注意:4G以上卡不是在这个位置,找度娘去.

注意框框中的选项



打开SD_BOOT bin文件,全部选中,复制



切换到SD卡的指定位置

右键->编辑->剪贴板数据->写入


一定要在指定的扇区开始写入,写入之后不要忘记保存


另一个需要启动的程序也可以用这个工具看看他的位置

注意一定要看物理扇区编号


主要由于8K代码中无法添加文件系统,如果这个代码启动后就可以无限制了,界面什么的都可以添加进去,后面将会完善L2的代码,实现更加方便的功能.


附上工程RVDS4.0的设置

L1的代码设置


为了减小代码体积,优化等级开高一点,平时测试可以开最低.





L2代码工程


其他位置设置都是一样的




附上工程下载位置:http://download.csdn.net/detail/cp1300/6694183

我使用的是RVDS4.0,想下载或使用的可以看看我的博文,里面详细介绍了RVDS4.0的安装以及设置.

http://blog.csdn.net/cp1300/article/details/7772645//安装

http://blog.csdn.net/cp1300/article/details/7772809//建立工程

http://blog.csdn.net/cp1300/article/details/8164042//调试

http://blog.csdn.net/cp1300/article/details/8237076//调试补丁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值